Boost logo

Boost :

From: Terje Slettebø (tslettebo_at_[hidden])
Date: 2004-09-18 05:44:35


>From: "Andy Little" <andy_at_[hidden]>

> "Terje Slettebø" <tslettebo_at_[hidden]> wrote
>
> #include <boost/operator_traits/has_plus_op.hpp>
> #include <boost/operator_traits/has_minus_op.hpp>
> #include <boost/concept_traits/std/is_assignable.hpp>
>
> template<class T1,class T2>
> struct is_my_concept :
> mpl::and_<
> is_assignable<T1>,
> is_assignable<T2>,
> has_plus_op<T1, T2>,
> has_minus_op<T1, T2>
> > {};
>
> Why not :
>
> has_op< T1,plus, T2> ?
>
> hence:
>
> #include <boost/operator_traits/has_ops.hpp>
>
> template<class T1, class Opa, class Opb,class T2>
> struct is_my_concept :
> mpl::and_<
> is_assignable<T1>,
> is_assignable<T2>,
> has_op<T1, Opa,T2>,
> has_op<T1, Opb, T2>
> > {};
>
> eg
> + -
> * /
>
> believe me this saves a lot of coding.

Thanks for your thoughts. The problem is that, despite what one might think,
the implementation of the traits to test for +, - * and / are different,
sometimes subtly, sometimes more.

Have a look, this is has_plus_op:

BOOST_OT_DETAIL_DEFINE_BINOP_TRAIT(has_plus_op_impl, +)

template<class T,class U = T>
struct has_plus_op :
  mpl::and_<
    mpl::or_<
      mpl::and_<
        detail::is_arithmetic_or_enum<typename remove_reference<T>::type>,
        detail::is_arithmetic_or_enum<typename remove_reference<U>::type>
>,
      mpl::and_<
        mpl::or_<
          is_array<typename remove_reference<T>::type>,
          detail::is_object_pointer<typename remove_reference<T>::type>
>,
        detail::is_integral_or_enum<typename remove_reference<U>::type>
>,
      mpl::and_<
        detail::is_integral_or_enum<typename remove_reference<T>::type>,
        mpl::or_<
          is_array<typename remove_reference<U>::type>,
          detail::is_object_pointer<typename remove_reference<U>::type>
>
>,
      detail::either_is_class_or_union_and_not_void<T,U>
>,
    detail::has_plus_op_impl<T,U>
> {};

and this is has_multiply_op:

BOOST_OT_DETAIL_DEFINE_BINOP_TRAIT(has_multiply_op_impl, *)

template<class T,class U = T>
struct has_multiply_op :
  mpl::and_<
    mpl::or_<
      mpl::and_<
        detail::is_arithmetic_or_enum<typename remove_reference<T>::type>,
        detail::is_arithmetic_or_enum<typename remove_reference<U>::type>
>,
      detail::either_is_class_or_union_and_not_void<T,U>
>,
    detail::has_multiply_op_impl<T,U>
> {};

Can you see the difference? ;)

Even for + and -, there are differences, such as that you can subtract two
pointers, but not add them.

For this reason, I felt it was best that each trait has a separate file, and
that avoids including more than necessary. For the cases where there's
reasonable commonality between the traits (such as the comparision
operators), the commonality is factored out into a header in the
detail-directory (and namespace), which is included in the relevant trait
headers.

In any case, one can always do:

#include <boost/operator_traits/operator_traits.hpp>

to get all the operator traits (same way to get the std concept traits, and
the MPL concept traits), just like Boost type traits. However, that drags in
everything, so unless you're doing a unit test on it all, it could seriously
degrade compilation time doing that.

I'm not sure if I answered your concerns, and if I didn't, please let me
know.

Regards,

Terje


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk