
From: "Andy Little" <andy@servocomm.freeserve.co.uk>
"Terje Slettebø" <tslettebo@broadpark.no> 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