Boost logo

Boost :

Subject: Re: [boost] [type_traits] adding is_less_comparable<T>, etc.
From: Frédéric Bron (frederic.bron_at_[hidden])
Date: 2009-09-03 07:28:56


> Thanks for all contributions. It works very fine now.
> 1. the key is the use of the ... argument instead of a template parameter
> 2. there is no difference between using a factory function and using a
> static reference to a value of the type -> I prefer the static
> reference
> 3. there is no difference between using pass/fail and return char or
> char[2] but pass/fail is easier to read -> I keep it
>
> So the following code has the following properties:
> * returns true if t<u is meaningful and returns a value convertible to bool
> * returns false if t<u is meaningless.
> * fails with compile time error if t<u is meaningful and returns void
>
> If you agree with the implementation, I will modify the sandbox
> accordingly and propose a new submission.
> Can I add your names in the copyright notice ? (Robert Stewart, Steven
> Watanabe, Roman Perepelitsa).

Please, are you happy with that? I would be very happy if included in
the next version and deadline is 13th of Septembre.
Thanks in advance, Frédéric

> #include <iostream>
> #include <boost/type_traits/remove_cv.hpp>
> #include <boost/type_traits/integral_constant.hpp>
>
> namespace boost {
> namespace detail {
>
> // This namespace ensures that ADL does not mess things up.
> namespace is_less_comparable_impl {
>
> // a type returned from comparison operator when no such operator is
> found in the
> // type's own namespace
> struct tag { } ;
>
> // any soaks up implicit conversions and makes the following
> // comparison operators less-preferred than any other such operators that
> // might be found via ADL.
> struct any { template <class T> any(T const&) ; } ;
>
> // when operator< is not available, this one is used
> tag operator<(const any&, const any&) ;
>
> typedef char pass ;
> struct fail { char dummy[2] ; } ;
>
> pass is_bool(bool) ; // this version is preferred for types convertible to bool
> fail is_bool(...) ; // this version is used otherwise
>
> template < typename T, typename U >
> struct is_less_comparable_impl {
>        static typename boost::remove_cv<T>::type &t ;
>        static typename boost::remove_cv<U>::type &u ;
>        static const bool value = sizeof(is_bool(t<u)) == sizeof(pass) ;
> } ;
>
> } // namespace impl
> } // namespace detail
>
> template< typename T, typename U=T >
> struct is_less_comparable :
> boost::integral_constant<bool,(::boost::detail::is_less_comparable_impl::is_less_comparable_impl<T,U>::value)>
> { } ;
>
> } // namespace boost
>
> // for testing
> struct NotComparable { } ;
> struct Comparable { bool operator<(const Comparable&) const ; } ;
> struct IntComparable { int operator<(const IntComparable&) ; } ;
> struct PtrComparable { void *operator<(const PtrComparable&) ; } ;
> // this one has a strange operator<: it returns a non standard type
> convertible to bool
> struct Convertible { operator bool () const ; } ;
> struct StrangeComparable { Convertible operator<(const StrangeComparable&) ; } ;
> struct VoidComparable { void operator<(const VoidComparable&) ; } ;
>
> #define TEST1(T)\
>        std::cout << boost::is_less_comparable<T, T>::value << "\t(" << #T <<
> '<' << #T << ")\n"
>
> #define TEST2(T1,T2)\
>        std::cout << boost::is_less_comparable<T1, T2>::value << "\t(" << #T1
> << '<' << #T2 << ")\n" ;\
>        std::cout << boost::is_less_comparable<T2, T1>::value << "\t(" << #T2
> << '<' << #T1 << ")\n"
>
>
> int main() {
>        std::cout << std::boolalpha ;
>
>        TEST1(NotComparable) ;
>        TEST1(Comparable) ;
>        TEST1(IntComparable) ;
>        TEST1(PtrComparable) ;
>        TEST1(StrangeComparable) ;
>        // the following line triggers a compile time error
>        //TEST1(VoidComparable) ;
>
>        TEST2(double, NotComparable) ;
>        TEST2(int, NotComparable) ;
>        TEST2(double, IntComparable) ;
>        TEST2(int, IntComparable) ;
>        TEST2(double, Comparable) ;
>        TEST2(int, Comparable) ;
>
>        TEST2(int, char) ;
>        TEST2(int, short) ;
>        TEST2(int, long) ;
>        TEST2(int, float) ;
>        TEST2(int, double) ;
>        return 0 ;
> }


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