1[/ 2 (C) Copyright 2009-2011 Frederic Bron. 3 Distributed under the Boost Software License, Version 1.0. 4 (See accompanying file LICENSE_1_0.txt or copy at 5 http://www.boost.org/LICENSE_1_0.txt). 6] 7 8[section:has_less has_less] 9 template <class Lhs, class Rhs=Lhs, class Ret=dont_care> 10 struct has_less : public __tof {}; 11 12__inherit 13If (i) `lhs` of type `Lhs` and `rhs` of type `Rhs` can be used in expression `lhs<rhs`, 14and (ii) `Ret=dont_care` or the result of expression `lhs<rhs` is convertible to `Ret` 15then inherits from __true_type, 16otherwise inherits from __false_type. 17 18The default behaviour (`Ret=dont_care`) is to not check for the return value of binary `operator<`. 19If `Ret` is different from the default `dont_care` type, the return value is checked to be convertible to `Ret`. 20Convertible to `Ret` means that the return value of the operator can be used as argument to a function expecting `Ret`: 21`` 22void f(Ret); 23Lhs lhs; 24Rhs rhs; 25f(lhs<rhs); // is valid if has_less<Lhs, Rhs, Ret>::value==true 26`` 27If `Ret=void`, the return type is checked to be exactly `void`. 28 29__header `#include <boost/type_traits/has_less.hpp>` or `#include <boost/type_traits/has_operator.hpp>` or `#include <boost/type_traits.hpp>` 30 31__examples 32 33[:`has_less<Lhs, Rhs, Ret>::value_type` is the type `bool`.] 34[:`has_less<Lhs, Rhs, Ret>::value` is a `bool` integral constant expression.] 35[:`has_less<int>::value` is a `bool` integral constant expression that evaluates to `true`.] 36[:`has_less<long>` inherits from `__true_type`.] 37 38[:`has_less<int, int, bool>` inherits from `__true_type`.] 39[:`has_less<int, double, bool>` inherits from `__true_type`.] 40[:`has_less<const int>` inherits from `__true_type`.] 41 42[:`has_less<int*, int>` inherits from `__false_type`.] 43[:`has_less<int*, double*>` inherits from `__false_type`.] 44[:`has_less<int, int, std::string>` inherits from `__false_type`.] 45 46 47[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits] 48 49[*Limitation:] 50 51* Requires a compiler with working SFINAE. 52 53[*Known issues:] 54 55* This trait cannot detect whether binary `operator<` is public or not: 56if `operator<` is defined as a private member of `Lhs` then 57instantiating `has_less<Lhs>` will produce a compiler error. 58For this reason `has_less` cannot be used to determine whether a type has a public `operator<` or not. 59`` 60struct A { private: void operator<(const A&); }; 61boost::has_less<A>::value; // error: A::operator<(const A&) is private 62`` 63 64* There is an issue if the operator exists only for type `A` and `B` is 65convertible to `A`. In this case, the compiler will report an ambiguous overload. 66`` 67struct A { }; 68void operator<(const A&, const A&); 69struct B { operator A(); }; 70boost::has_less<A>::value; // this is fine 71boost::has_less<B>::value; // error: ambiguous overload 72`` 73 74* There is an issue when applying this trait to template classes. 75If `operator<` is defined but does not bind for a given template type, 76it is still detected by the trait which returns `true` instead of `false`. 77Example: 78`` 79#include <boost/type_traits/has_less.hpp> 80#include <iostream> 81 82template <class T> 83struct contains { T data; }; 84 85template <class T> 86bool operator<(const contains<T> &lhs, const contains<T> &rhs) { 87 return f(lhs.data, rhs.data); 88} 89 90class bad { }; 91class good { }; 92bool f(const good&, const good&) { } 93 94int main() { 95 std::cout<<std::boolalpha; 96 // works fine for contains<good> 97 std::cout<<boost::has_less< contains< good > >::value<<'\n'; // true 98 contains<good> g; 99 g<g; // ok 100 // does not work for contains<bad> 101 std::cout<<boost::has_less< contains< bad > >::value<<'\n'; // true, should be false 102 contains<bad> b; 103 b<b; // compile time error 104 return 0; 105} 106`` 107 108* `volatile` qualifier is not properly handled and would lead to undefined behavior 109 110[endsect] 111 112