Boost logo

Proto :

Subject: Re: [proto] [Spirit-devel] [Spirit Development] Bug in today's boost_trunk -- ambiguous operator >
From: Hartmut Kaiser (hartmut.kaiser_at_[hidden])
Date: 2010-12-23 21:42:55


> >> I have a fairly large program that compiled just fine on boost_trunk
> >> version 67416, but is now broken. I traced to problem to an
> >> ambiguous operator overload that occurs when both qi.hpp and
> >> fusion/tuple.hpp are included.
> >>
> >> The following code does not compile as of today, but should compile
> >> on version 67416.
> >>
> >> #include <boost/fusion/tuple.hpp> //including this file caused
> >> ambiguity errors #include <boost/spirit/include/qi.hpp> #include
> >> <string>
> >>
> >> int main()
> >> {
> >> static const boost::spirit::qi::rule<std::string::const_iterator> a;
> >> static const boost::spirit::qi::rule<std::string::const_iterator> b;
> >> boost::spirit::qi::rule<std::string::const_iterator> rule = a > b;
> >> }
> >>
> >
> > Ohh, that looks serious! The ambiguity is caused by a proto/fusion
> overlap.
> > A qi::rule is both, a proto expression and a fusion sequence (as all
> > proto expressions are proto sequences now).
> >
> > Proto's overload for operator>() is a valid choice for this, as is
> > fusions
> > operator>().
> >
> > I'm cc'ing Eric and Christopher, perhaps they have an idea how to
> proceed.
>
> I suggest defining a Fusion trait, is_less_then_comparable, and define it
> for the built-in Fusion sequences (tuple, vector, etc.). That can be used
> to SFINAE out Fusion's operator<, which should not be picked up for Proto
> expressions. Ditto for the other operations on Fusion sequences.
>
> I have no better ideas at the moment.

Fusion already has a traits class for this, but it's not SFINAE enabled (see
boost/fusion/sequence/comparison/detail/enable_comparison.hpp), even if it's
in 'namespace detail'.

Adding an additional template parameter to make it into a customization
point:

namespace boost { namespace fusion { namespace detail
{
    template <typename Seq1, typename Seq2, typename Enable = void>
    struct enable_equality ...

    template <typename Seq1, typename Seq2, typename Enable = void>
    struct enable_comparison ...
}}}

which allows to add:

namespace boost { namespace fusion { namespace detail
{
    template <typename T1, typename T2>
    struct enable_equality<T1, T2,
          typename enable_if<mpl::or_<proto::is_expr<T1>, proto::is_expr<T2>
> >::type>
      : mpl::false_
    {};

    template <typename T1, typename T2>
    struct enable_comparison<T1, T2,
          typename enable_if<mpl::or_<proto::is_expr<T1>, proto::is_expr<T2>
> >::type>
      : mpl::false_
    {};
}}}

I'm currently running the Fusion tests to see whether the additional
'typename Enable = void' break anything. But I expect everything to work -
Yep everything is fine.

Eric, would you be willing to add the specializations above to Proto's
Fusion adaptation code?

Regards Hartmut
---------------
http://boost-spirit.com


Proto list run by eric at boostpro.com