
Frédéric Bron wrote:
Is it reasonable to additionally verify the returned type? IMO, such kind of traits should not make assumptions about the operators meaning, they should merely show whether the comparison expression is valid. Thus there also should not be a fails-to-compile case.
OK, what do you know if you know that you can write t<u but do not know if it is convertible to bool? You know that "t<u ;" is OK but maybe "if (t<u) ..." will not work -> compile time error. I think that in most cases you want to know that it behaves like operator< used with built-in types.
Knowing that an expression is valid and that the expression can be used in a specific context are different things. Therefore I would like to see the tools that provide these two kinds of knowledge decoupled. Otherwise you make these traits bound to a single specific use case, no matter how widely used it is.
Maybe it could be interesting for some people to have an additionnal version just checking for existence but I am not convinced.
I agree that it is not "nice" to have a compile time error when used with operator< returning void but I prefer that than returning true because this behaviour is not the one expected by operator<. If anybody has a solution on how to return false in such case...
You can achieve that with typeof/decltype. Something like that (not tested): #include <boost/type.hpp> namespace adl_block { struct something_else {}; struct convertible_from_any { template< typename T > convertible_from_any(T const&); }; something_else operator< ( convertible_from_any, convertible_from_any); template< typename T, typename U > struct is_less_comparable_impl { typedef char yes_type; struct no_type { char _[2]; }; template< typename V > static yes_type check(type< V > const&); static no_type check(type< something_else > const&); static T make_T(); static U make_U(); enum _ { value = sizeof(yes_type) == sizeof(check(type< decltype(make_T() < make_U()) >())) }; }; } template< typename T, typename U > struct is_less_comparable : mpl::bool_< adl_block::is_less_comparable_impl< T, U >::value > { };