diff --git a/include/boost/intrusive/avltree.hpp b/include/boost/intrusive/avltree.hpp index 1996d69..9ebb483 100644 --- a/include/boost/intrusive/avltree.hpp +++ b/include/boost/intrusive/avltree.hpp @@ -404,33 +404,23 @@ class avltree_impl //! @copydoc ::boost::intrusive::bstree::remove_node void remove_node(reference value); + + friend bool operator< (const avltree_impl &x, const avltree_impl &y); + + friend bool operator==(const avltree_impl &x, const avltree_impl &y); + + friend bool operator!= (const avltree_impl &x, const avltree_impl &y); + + friend bool operator>(const avltree_impl &x, const avltree_impl &y); + + friend bool operator<=(const avltree_impl &x, const avltree_impl &y); + + friend bool operator>=(const avltree_impl &x, const avltree_impl &y); + + friend void swap(avltree_impl &x, avltree_impl &y); #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) - -template -bool operator< (const avltree_impl &x, const avltree_impl &y); - -template -bool operator==(const avltree_impl &x, const avltree_impl &y); - -template -bool operator!= (const avltree_impl &x, const avltree_impl &y); - -template -bool operator>(const avltree_impl &x, const avltree_impl &y); - -template -bool operator<=(const avltree_impl &x, const avltree_impl &y); - -template -bool operator>=(const avltree_impl &x, const avltree_impl &y); - -template -void swap(avltree_impl &x, avltree_impl &y); - -#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Helper metafunction to define a \c avltree that yields to the same type when the //! same options (either explicitly or implicitly) are used. diff --git a/include/boost/intrusive/bstree.hpp b/include/boost/intrusive/bstree.hpp index 39c9d3e..302cb23 100644 --- a/include/boost/intrusive/bstree.hpp +++ b/include/boost/intrusive/bstree.hpp @@ -1366,11 +1366,9 @@ class bstree_impl //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. template - size_type erase(const KeyType& key, KeyValueCompare comp - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) + BOOST_INTRUSIVE_DOC1ST(size_type + , typename detail::disable_if_convertible::type) + erase(const KeyType& key, KeyValueCompare comp) { std::pair p = this->equal_range(key, comp); size_type n; @@ -1398,12 +1396,6 @@ class bstree_impl return ret; } - #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) - template - iterator erase_and_dispose(iterator i, Disposer disposer) - { return this->erase_and_dispose(const_iterator(i), disposer); } - #endif - //! Requires: Disposer::operator()(pointer) shouldn't throw. //! //! Effects: Erases all the elements with the given value. @@ -1457,11 +1449,9 @@ class bstree_impl //! Note: Invalidates the iterators //! to the erased elements. template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) + BOOST_INTRUSIVE_DOC1ST(size_type + , typename detail::disable_if_convertible::type) + erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer) { std::pair p = this->equal_range(key, comp); size_type n; @@ -1956,6 +1946,32 @@ class bstree_impl check(detail::empty_node_checker()); } + friend bool operator==(const bstree_impl &x, const bstree_impl &y) + { + if(constant_time_size && x.size() != y.size()){ + return false; + } + return boost::intrusive::algo_equal(x.cbegin(), x.cend(), y.cbegin(), y.cend()); + } + + friend bool operator!=(const bstree_impl &x, const bstree_impl &y) + { return !(x == y); } + + friend bool operator<(const bstree_impl &x, const bstree_impl &y) + { return ::boost::intrusive::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } + + friend bool operator>(const bstree_impl &x, const bstree_impl &y) + { return y < x; } + + friend bool operator<=(const bstree_impl &x, const bstree_impl &y) + { return !(x > y); } + + friend bool operator>=(const bstree_impl &x, const bstree_impl &y) + { return !(x < y); } + + friend void swap(bstree_impl &x, bstree_impl &y) + { x.swap(y); } + /// @cond private: template @@ -1975,111 +1991,6 @@ class bstree_impl /// @endcond }; -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator< -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const bstree_impl &x, const bstree_impl &y) -#else -( const bstree_impl &x -, const bstree_impl &y) -#endif -{ return ::boost::intrusive::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -bool operator== -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const bstree_impl &x, const bstree_impl &y) -#else -( const bstree_impl &x -, const bstree_impl &y) -#endif -{ - typedef bstree_impl tree_type; - - if(tree_type::constant_time_size && x.size() != y.size()){ - return false; - } - return boost::intrusive::algo_equal(x.cbegin(), x.cend(), y.cbegin(), y.cend()); -} - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator!= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const bstree_impl &x, const bstree_impl &y) -#else -( const bstree_impl &x -, const bstree_impl &y) -#endif -{ return !(x == y); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator> -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const bstree_impl &x, const bstree_impl &y) -#else -( const bstree_impl &x -, const bstree_impl &y) -#endif -{ return y < x; } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator<= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const bstree_impl &x, const bstree_impl &y) -#else -( const bstree_impl &x -, const bstree_impl &y) -#endif -{ return !(y < x); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator>= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const bstree_impl &x, const bstree_impl &y) -#else -( const bstree_impl &x -, const bstree_impl &y) -#endif -{ return !(x < y); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline void swap -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(bstree_impl &x, bstree_impl &y) -#else -( bstree_impl &x -, bstree_impl &y) -#endif -{ x.swap(y); } - //! Helper metafunction to define a \c bstree that yields to the same type when the //! same options (either explicitly or implicitly) are used. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) diff --git a/include/boost/intrusive/bstree_algorithms.hpp b/include/boost/intrusive/bstree_algorithms.hpp index f7e915e..dcb7e5c 100644 --- a/include/boost/intrusive/bstree_algorithms.hpp +++ b/include/boost/intrusive/bstree_algorithms.hpp @@ -37,10 +37,6 @@ namespace intrusive { template struct insert_commit_data_t { - insert_commit_data_t() - : link_left(false) - , node() - {} bool link_left; NodePtr node; }; diff --git a/include/boost/intrusive/detail/get_value_traits.hpp b/include/boost/intrusive/detail/get_value_traits.hpp index 686e059..222f807 100644 --- a/include/boost/intrusive/detail/get_value_traits.hpp +++ b/include/boost/intrusive/detail/get_value_traits.hpp @@ -107,9 +107,9 @@ BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(internal_base_hook, hooktags::is_ba template struct internal_member_value_traits { - template static one test(...); - template static two test(typename U::member_value_traits* = 0); - static const bool value = sizeof(test(0)) == sizeof(two); + template static yes_type test(...); + template static no_type test(typename U::member_value_traits* = 0); + static const bool value = sizeof(test(0)) == sizeof(no_type); }; template::value> diff --git a/include/boost/intrusive/detail/hashtable_node.hpp b/include/boost/intrusive/detail/hashtable_node.hpp index 923a3e1..fcfae3b 100644 --- a/include/boost/intrusive/detail/hashtable_node.hpp +++ b/include/boost/intrusive/detail/hashtable_node.hpp @@ -113,9 +113,9 @@ struct bucket_traits_impl template struct hash_reduced_slist_node_traits { - template static detail::one test(...); - template static detail::two test(typename U::reduced_slist_node_traits* = 0); - static const bool value = sizeof(test(0)) == sizeof(detail::two); + template static detail::no_type test(...); + template static detail::yes_type test(typename U::reduced_slist_node_traits*); + static const bool value = sizeof(test(0)) == sizeof(detail::yes_type); }; template diff --git a/include/boost/intrusive/detail/is_stateful_value_traits.hpp b/include/boost/intrusive/detail/is_stateful_value_traits.hpp index 680b043..e43f6d3 100644 --- a/include/boost/intrusive/detail/is_stateful_value_traits.hpp +++ b/include/boost/intrusive/detail/is_stateful_value_traits.hpp @@ -32,7 +32,7 @@ namespace detail { template struct is_stateful_value_traits { - static const bool value = !detail::is_empty_class::value; + static const bool value = !detail::is_empty::value; }; }}} diff --git a/include/boost/intrusive/detail/key_nodeptr_comp.hpp b/include/boost/intrusive/detail/key_nodeptr_comp.hpp index 8c45663..c7d81eb 100644 --- a/include/boost/intrusive/detail/key_nodeptr_comp.hpp +++ b/include/boost/intrusive/detail/key_nodeptr_comp.hpp @@ -51,12 +51,13 @@ struct key_nodeptr_comp //key_forward template - const value_type & key_forward - (const T &node, typename enable_if_c::value>::type * = 0) const + typename enable_if, const value_type &>::type + key_forward(const T &node) const { return *traits_->to_value_ptr(node); } template - const T & key_forward(const T &key, typename enable_if_c::value>::type* = 0) const + typename disable_if, const T &>::type + const key_forward(const T &key) const { return key; } //operator() 1 arg diff --git a/include/boost/intrusive/detail/math.hpp b/include/boost/intrusive/detail/math.hpp index 03000fc..dfebe2a 100644 --- a/include/boost/intrusive/detail/math.hpp +++ b/include/boost/intrusive/detail/math.hpp @@ -127,7 +127,7 @@ namespace detail { { return (n >> 1) + ((n & 1u) & (n != 1)); } template - inline std::size_t floor_log2 (std::size_t x, integer) + inline std::size_t floor_log2 (std::size_t x, integral_constant) { const std::size_t Bits = N; const bool Size_t_Bits_Power_2= !(Bits & (Bits-1)); @@ -156,7 +156,7 @@ namespace detail { //http://stackoverflow.com/questions/11376288/fast-computing-of-log2-for-64-bit-integers //Thanks to Desmond Hume - inline std::size_t floor_log2 (std::size_t v, integer) + inline std::size_t floor_log2 (std::size_t v, integral_constant) { static const int MultiplyDeBruijnBitPosition[32] = { @@ -173,7 +173,7 @@ namespace detail { return MultiplyDeBruijnBitPosition[(std::size_t)(v * 0x07C4ACDDU) >> 27]; } - inline std::size_t floor_log2 (std::size_t v, integer) + inline std::size_t floor_log2 (std::size_t v, integral_constant) { static const std::size_t MultiplyDeBruijnBitPosition[64] = { 63, 0, 58, 1, 59, 47, 53, 2, @@ -198,7 +198,7 @@ namespace detail { inline std::size_t floor_log2 (std::size_t x) { const std::size_t Bits = sizeof(std::size_t)*CHAR_BIT; - return floor_log2(x, integer()); + return floor_log2(x, integral_constant()); } #endif diff --git a/include/boost/intrusive/detail/mpl.hpp b/include/boost/intrusive/detail/mpl.hpp index 39d2c58..dc57b98 100644 --- a/include/boost/intrusive/detail/mpl.hpp +++ b/include/boost/intrusive/detail/mpl.hpp @@ -23,260 +23,47 @@ #endif #include +#include #include namespace boost { namespace intrusive { namespace detail { - -template -struct is_same -{ - static const bool value = false; -}; - -template -struct is_same -{ - static const bool value = true; -}; - -template -struct add_const -{ typedef const T type; }; - -template -struct remove_const -{ typedef T type; }; - -template -struct remove_const -{ typedef T type; }; - -template -struct remove_cv -{ typedef T type; }; - -template -struct remove_cv -{ typedef T type; }; - -template -struct remove_cv -{ typedef T type; }; - -template -struct remove_cv -{ typedef T type; }; - -template -struct remove_reference -{ - typedef T type; -}; - -template -struct remove_reference -{ - typedef T type; -}; - -template -struct remove_pointer -{ - typedef T type; -}; - -template -struct remove_pointer -{ - typedef T type; -}; - -template -struct add_pointer -{ - typedef T *type; -}; - -typedef char one; -struct two {one _[2];}; - -template< bool C_ > -struct bool_ -{ - static const bool value = C_; -}; - -template< class Integer, Integer Value > -struct integer -{ - static const Integer value = Value; -}; - -typedef bool_ true_; -typedef bool_ false_; - -typedef true_ true_type; -typedef false_ false_type; - -typedef char yes_type; -struct no_type -{ - char padding[8]; -}; - -template -struct enable_if_c { - typedef T type; -}; - -template -struct enable_if_c {}; - -template -struct enable_if : public enable_if_c{}; - -template -struct apply -{ - typedef typename F::template apply::type type; -}; - -#if defined(_MSC_VER) && (_MSC_VER >= 1400) - -template -struct is_convertible -{ - static const bool value = __is_convertible_to(T, U); -}; - -#else - -template -class is_convertible -{ - typedef char true_t; - class false_t { char dummy[2]; }; - //use any_conversion as first parameter since in MSVC - //overaligned types can't go through ellipsis - static false_t dispatch(...); - static true_t dispatch(U); - static typename remove_reference::type &trigger(); - public: - static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t); -}; - -#endif - -template< - bool C - , typename T1 - , typename T2 - > -struct if_c -{ - typedef T1 type; -}; - -template< - typename T1 - , typename T2 - > -struct if_c -{ - typedef T2 type; -}; - -template< - typename C - , typename T1 - , typename T2 - > -struct if_ -{ - typedef typename if_c<0 != C::value, T1, T2>::type type; -}; - -template< - bool C - , typename F1 - , typename F2 - > -struct eval_if_c - : if_c::type -{}; - -template< - typename C - , typename T1 - , typename T2 - > -struct eval_if - : if_::type -{}; - -// identity is an extension: it is not part of the standard. -template -struct identity -{ - typedef T type; -}; - -template -struct add_const_if_c -{ - typedef typename if_c - < Add - , typename add_const::type - , T - >::type type; -}; - - -//boost::alignment_of yields to 10K lines of preprocessed code, so we -//need an alternative -template struct alignment_of; - -template -struct alignment_of_hack -{ - char c; - T t; - alignment_of_hack(); -}; - -template -struct alignment_logic -{ - static const std::size_t value = A < S ? A : S; -}; - -template< typename T > -struct alignment_of -{ - static const std::size_t value = alignment_logic - < sizeof(alignment_of_hack) - sizeof(T) - , sizeof(T) - >::value; -}; - -template -class is_empty_class -{ - template - struct empty_helper_t1 : public T - { - empty_helper_t1(); - int i[256]; - }; - - struct empty_helper_t2 - { int i[256]; }; - - public: - static const bool value = sizeof(empty_helper_t1) == sizeof(empty_helper_t2); -}; + +using boost::move_detail::is_same; +using boost::move_detail::add_const; +using boost::move_detail::remove_const; +using boost::move_detail::remove_cv; +using boost::move_detail::remove_reference; +using boost::move_detail::add_reference; +using boost::move_detail::remove_pointer; +using boost::move_detail::add_pointer; +using boost::move_detail::true_type; +using boost::move_detail::false_type; +using boost::move_detail::enable_if_c; +using boost::move_detail::enable_if; +using boost::move_detail::disable_if_c; +using boost::move_detail::disable_if; +using boost::move_detail::is_convertible; +using boost::move_detail::if_c; +using boost::move_detail::if_; +using boost::move_detail::identity; +using boost::move_detail::alignment_of; +using boost::move_detail::is_empty; +using boost::move_detail::addressof; +using boost::move_detail::integral_constant; +using boost::move_detail::enable_if_convertible; +using boost::move_detail::disable_if_convertible; +using boost::move_detail::bool_; +using boost::move_detail::true_; +using boost::move_detail::false_; +using boost::move_detail::yes_type; +using boost::move_detail::no_type; +using boost::move_detail::apply; +using boost::move_detail::eval_if_c; +using boost::move_detail::eval_if; +using boost::move_detail::unvoid_ref; +using boost::move_detail::add_const_if_c; template struct ls_zeros @@ -296,10 +83,6 @@ struct ls_zeros<1> static const std::size_t value = 0; }; -template struct unvoid_ref { typedef T &type; }; -template <> struct unvoid_ref { struct type_impl { }; typedef type_impl & type; }; -template <> struct unvoid_ref { struct type_impl { }; typedef type_impl & type; }; - // Infrastructure for providing a default type for T::TNAME if absent. #define BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(TNAME) \ template \ @@ -360,8 +143,8 @@ template \ struct TRAITS_PREFIX##_bool\ {\ template\ - struct two_or_three {one _[2 + Add];};\ - template static one test(...);\ + struct two_or_three {yes_type _[2 + Add];};\ + template static yes_type test(...);\ template static two_or_three test (int);\ static const std::size_t value = sizeof(test(0));\ };\ @@ -369,7 +152,7 @@ struct TRAITS_PREFIX##_bool\ template \ struct TRAITS_PREFIX##_bool_is_true\ {\ - static const bool value = TRAITS_PREFIX##_bool::value > sizeof(one)*2;\ + static const bool value = TRAITS_PREFIX##_bool::value > sizeof(yes_type)*2;\ };\ // @@ -413,18 +196,6 @@ struct TRAITS_NAME \ {};\ // - -template -inline T* addressof(T& obj) -{ - return static_cast - (static_cast - (const_cast - (&reinterpret_cast(obj)) - ) - ); -} - } //namespace detail } //namespace intrusive } //namespace boost diff --git a/include/boost/intrusive/detail/reverse_iterator.hpp b/include/boost/intrusive/detail/reverse_iterator.hpp index 6a6fee5..9be10a9 100644 --- a/include/boost/intrusive/detail/reverse_iterator.hpp +++ b/include/boost/intrusive/detail/reverse_iterator.hpp @@ -23,6 +23,7 @@ #include #include +#include namespace boost { namespace intrusive { @@ -49,10 +50,17 @@ class reverse_iterator {} template - reverse_iterator(const reverse_iterator& r) + reverse_iterator( const reverse_iterator& r + , typename boost::intrusive::detail::enable_if_convertible::type* =0 + ) : m_current(r.base()) {} + template + typename boost::intrusive::detail::enable_if_convertible::type + operator=( const reverse_iterator& r) + { m_current = r.base(); return *this; } + It base() const { return m_current; } @@ -63,7 +71,7 @@ class reverse_iterator { It temp(m_current); --temp; return temp.operator->(); } reference operator[](difference_type off) const - { return this->m_current[-off-1]; } + { return this->m_current[-off - 1]; } reverse_iterator& operator++() { --m_current; return *this; } @@ -109,22 +117,17 @@ class reverse_iterator reverse_iterator& operator+=(difference_type off) { m_current -= off; return *this; } - friend reverse_iterator operator+(const reverse_iterator & l, difference_type off) - { - reverse_iterator tmp(l.m_current); - tmp.m_current -= off; - return tmp; - } + friend reverse_iterator operator+(reverse_iterator l, difference_type off) + { l.m_current -= off; return l; } + + friend reverse_iterator operator+(difference_type off, reverse_iterator r) + { return (r += off); } reverse_iterator& operator-=(difference_type off) { m_current += off; return *this; } - friend reverse_iterator operator-(const reverse_iterator & l, difference_type off) - { - reverse_iterator tmp(l.m_current); - tmp.m_current += off; - return tmp; - } + friend reverse_iterator operator-(reverse_iterator l, difference_type off) + { l.m_current += off; return l; } friend difference_type operator-(const reverse_iterator& l, const reverse_iterator& r) { return r.m_current - l.m_current; } diff --git a/include/boost/intrusive/detail/tree_iterator.hpp b/include/boost/intrusive/detail/tree_iterator.hpp index 525761f..c2e980d 100644 --- a/include/boost/intrusive/detail/tree_iterator.hpp +++ b/include/boost/intrusive/detail/tree_iterator.hpp @@ -40,13 +40,11 @@ namespace intrusive { template class tree_iterator { - protected: + private: typedef iiterator< ValueTraits, IsConst , std::bidirectional_iterator_tag> types_t; - - typedef ValueTraits value_traits; + typedef typename types_t::value_traits value_traits; typedef typename types_t::node_traits node_traits; - typedef typename types_t::node node; typedef typename types_t::node_ptr node_ptr; typedef typename types_t::const_value_traits_ptr const_value_traits_ptr; diff --git a/include/boost/intrusive/hashtable.hpp b/include/boost/intrusive/hashtable.hpp index 1d4f3d3..6c39215 100644 --- a/include/boost/intrusive/hashtable.hpp +++ b/include/boost/intrusive/hashtable.hpp @@ -172,8 +172,8 @@ template struct store_hash_bool { template - struct two_or_three {one _[2 + Add];}; - template static one test(...); + struct two_or_three {yes_type _[2 + Add];}; + template static yes_type test(...); template static two_or_three test (int); static const std::size_t value = sizeof(test(0)); }; @@ -181,15 +181,15 @@ struct store_hash_bool template struct store_hash_is_true { - static const bool value = store_hash_bool::value > sizeof(one)*2; + static const bool value = store_hash_bool::value > sizeof(yes_type)*2; }; template struct optimize_multikey_bool { template - struct two_or_three {one _[2 + Add];}; - template static one test(...); + struct two_or_three {yes_type _[2 + Add];}; + template static yes_type test(...); template static two_or_three test (int); static const std::size_t value = sizeof(test(0)); }; @@ -197,7 +197,7 @@ struct optimize_multikey_bool template struct optimize_multikey_is_true { - static const bool value = optimize_multikey_bool::value > sizeof(one)*2; + static const bool value = optimize_multikey_bool::value > sizeof(yes_type)*2; }; struct insert_commit_data_impl @@ -1887,11 +1887,9 @@ class hashtable_impl //! Note: Invalidates the iterators //! to the erased elements. template - void erase_and_dispose(const_iterator i, Disposer disposer - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) + BOOST_INTRUSIVE_DOC1ST(void + , typename detail::disable_if_convertible::type) + erase_and_dispose(const_iterator i, Disposer disposer) { this->priv_erase(i, disposer, optimize_multikey_t()); this->priv_size_traits().decrement(); @@ -2774,6 +2772,37 @@ class hashtable_impl bound -= (bound != primes); return size_type(*bound); } + + friend bool operator==(const hashtable_impl &x, const hashtable_impl &y) + { + if(constant_time_size && x.size() != y.size()){ + return false; + } + //Find each element of x in y + for (const_iterator ix = x.cbegin(), ex = x.cend(), ey = y.cend(); ix != ex; ++ix) + { + const_iterator iy = y.find(*ix); + if (iy == ey || !(*ix == *iy)) + return false; + } + return true; + } + + friend bool operator!=(const hashtable_impl &x, const hashtable_impl &y) + { return !(x == y); } + + friend bool operator<(const hashtable_impl &x, const hashtable_impl &y) + { return ::boost::intrusive::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } + + friend bool operator>(const hashtable_impl &x, const hashtable_impl &y) + { return y < x; } + + friend bool operator<=(const hashtable_impl &x, const hashtable_impl &y) + { return !(y < x); } + + friend bool operator>=(const hashtable_impl &x, const hashtable_impl &y) + { return !(x < y); } + /// @cond void check() const {} private: diff --git a/include/boost/intrusive/list.hpp b/include/boost/intrusive/list.hpp index 906b002..77a1378 100644 --- a/include/boost/intrusive/list.hpp +++ b/include/boost/intrusive/list.hpp @@ -1320,6 +1320,32 @@ class list_impl BOOST_INTRUSIVE_INVARIANT_ASSERT(this->priv_size_traits().get_size() == node_count); } + friend bool operator==(const list_impl &x, const list_impl &y) + { + if(constant_time_size && x.size() != y.size()){ + return false; + } + return ::boost::intrusive::algo_equal(x.cbegin(), x.cend(), y.cbegin(), y.cend()); + } + + friend bool operator!=(const list_impl &x, const list_impl &y) + { return !(x == y); } + + friend bool operator<(const list_impl &x, const list_impl &y) + { return ::boost::intrusive::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } + + friend bool operator>(const list_impl &x, const list_impl &y) + { return y < x; } + + friend bool operator<=(const list_impl &x, const list_impl &y) + { return !(y < x); } + + friend bool operator>=(const list_impl &x, const list_impl &y) + { return !(x < y); } + + friend void swap(list_impl &x, list_impl &y) + { x.swap(y); } + /// @cond private: @@ -1338,103 +1364,6 @@ class list_impl /// @endcond }; -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator< -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const list_impl &x, const list_impl &y) -#else -(const list_impl &x, const list_impl &y) -#endif -{ return ::boost::intrusive::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -bool operator== -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const list_impl &x, const list_impl &y) -#else -(const list_impl &x, const list_impl &y) -#endif -{ - typedef list_impl list_type; - const bool C = list_type::constant_time_size; - if(C && x.size() != y.size()){ - return false; - } - return ::boost::intrusive::algo_equal(x.cbegin(), x.cend(), y.cbegin(), y.cend()); -} - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator!= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const list_impl &x, const list_impl &y) -#else -(const list_impl &x, const list_impl &y) -#endif -{ return !(x == y); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator> -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const list_impl &x, const list_impl &y) -#else -(const list_impl &x, const list_impl &y) -#endif -{ return y < x; } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator<= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const list_impl &x, const list_impl &y) -#else -(const list_impl &x, const list_impl &y) -#endif -{ return !(y < x); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator>= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const list_impl &x, const list_impl &y) -#else -(const list_impl &x, const list_impl &y) -#endif -{ return !(x < y); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline void swap -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(list_impl &x, list_impl &y) -#else -(list_impl &x, list_impl &y) -#endif -{ x.swap(y); } //! Helper metafunction to define a \c list that yields to the same type when the //! same options (either explicitly or implicitly) are used. diff --git a/include/boost/intrusive/rbtree.hpp b/include/boost/intrusive/rbtree.hpp index 4ef50b4..7b46b00 100644 --- a/include/boost/intrusive/rbtree.hpp +++ b/include/boost/intrusive/rbtree.hpp @@ -406,33 +406,23 @@ class rbtree_impl //! @copydoc ::boost::intrusive::bstree::remove_node void remove_node(reference value); + + friend bool operator< (const rbtree_impl &x, const rbtree_impl &y); + + friend bool operator==(const rbtree_impl &x, const rbtree_impl &y); + + friend bool operator!= (const rbtree_impl &x, const rbtree_impl &y); + + friend bool operator>(const rbtree_impl &x, const rbtree_impl &y); + + friend bool operator<=(const rbtree_impl &x, const rbtree_impl &y); + + friend bool operator>=(const rbtree_impl &x, const rbtree_impl &y); + + friend void swap(rbtree_impl &x, rbtree_impl &y); #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) - -template -bool operator< (const rbtree_impl &x, const rbtree_impl &y); - -template -bool operator==(const rbtree_impl &x, const rbtree_impl &y); - -template -bool operator!= (const rbtree_impl &x, const rbtree_impl &y); - -template -bool operator>(const rbtree_impl &x, const rbtree_impl &y); - -template -bool operator<=(const rbtree_impl &x, const rbtree_impl &y); - -template -bool operator>=(const rbtree_impl &x, const rbtree_impl &y); - -template -void swap(rbtree_impl &x, rbtree_impl &y); - -#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Helper metafunction to define a \c rbtree that yields to the same type when the //! same options (either explicitly or implicitly) are used. diff --git a/include/boost/intrusive/sgtree.hpp b/include/boost/intrusive/sgtree.hpp index feeaf3b..2a6ad68 100644 --- a/include/boost/intrusive/sgtree.hpp +++ b/include/boost/intrusive/sgtree.hpp @@ -610,11 +610,9 @@ class sgtree_impl //! @copydoc ::boost::intrusive::bstree::erase(const KeyType&,KeyValueCompare) template - size_type erase(const KeyType& key, KeyValueCompare comp - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) + BOOST_INTRUSIVE_DOC1ST(size_type + , typename detail::disable_if_convertible::type) + erase(const KeyType& key, KeyValueCompare comp) { std::pair p = this->equal_range(key, comp); size_type n; @@ -655,11 +653,9 @@ class sgtree_impl //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) + BOOST_INTRUSIVE_DOC1ST(size_type + , typename detail::disable_if_convertible::type) + erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer) { std::pair p = this->equal_range(key, comp); size_type n; @@ -796,6 +792,20 @@ class sgtree_impl //! @copydoc ::boost::intrusive::bstree::rebalance_subtree iterator rebalance_subtree(iterator root); + friend bool operator< (const sgtree_impl &x, const sgtree_impl &y); + + friend bool operator==(const sgtree_impl &x, const sgtree_impl &y); + + friend bool operator!= (const sgtree_impl &x, const sgtree_impl &y); + + friend bool operator>(const sgtree_impl &x, const sgtree_impl &y); + + friend bool operator<=(const sgtree_impl &x, const sgtree_impl &y); + + friend bool operator>=(const sgtree_impl &x, const sgtree_impl &y); + + friend void swap(sgtree_impl &x, sgtree_impl &y); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! Returns: The balance factor (alpha) used in this tree @@ -850,30 +860,6 @@ class sgtree_impl /// @endcond }; -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) - -template -bool operator< (const sgtree_impl &x, const sgtree_impl &y); - -template -bool operator==(const sgtree_impl &x, const sgtree_impl &y); - -template -bool operator!= (const sgtree_impl &x, const sgtree_impl &y); - -template -bool operator>(const sgtree_impl &x, const sgtree_impl &y); - -template -bool operator<=(const sgtree_impl &x, const sgtree_impl &y); - -template -bool operator>=(const sgtree_impl &x, const sgtree_impl &y); - -template -void swap(sgtree_impl &x, sgtree_impl &y); - -#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Helper metafunction to define a \c sgtree that yields to the same type when the //! same options (either explicitly or implicitly) are used. diff --git a/include/boost/intrusive/slist.hpp b/include/boost/intrusive/slist.hpp index 7575081..7baf66b 100644 --- a/include/boost/intrusive/slist.hpp +++ b/include/boost/intrusive/slist.hpp @@ -1905,6 +1905,33 @@ class slist_impl BOOST_INTRUSIVE_INVARIANT_ASSERT(this->priv_size_traits().get_size() == node_count); } + + friend bool operator==(const slist_impl &x, const slist_impl &y) + { + if(constant_time_size && x.size() != y.size()){ + return false; + } + return ::boost::intrusive::algo_equal(x.cbegin(), x.cend(), y.cbegin(), y.cend()); + } + + friend bool operator!=(const slist_impl &x, const slist_impl &y) + { return !(x == y); } + + friend bool operator<(const slist_impl &x, const slist_impl &y) + { return ::boost::intrusive::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } + + friend bool operator>(const slist_impl &x, const slist_impl &y) + { return y < x; } + + friend bool operator<=(const slist_impl &x, const slist_impl &y) + { return !(y < x); } + + friend bool operator>=(const slist_impl &x, const slist_impl &y) + { return !(x < y); } + + friend void swap(slist_impl &x, slist_impl &y) + { x.swap(y); } + private: void priv_splice_after(const node_ptr & prev_pos_n, slist_impl &x, const node_ptr & before_f_n, const node_ptr & before_l_n) { @@ -2044,111 +2071,6 @@ class slist_impl } }; -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator< -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const slist_impl &x, const slist_impl &y) -#else -( const slist_impl &x -, const slist_impl &y) -#endif -{ return ::boost::intrusive::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -bool operator== -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const slist_impl &x, const slist_impl &y) -#else -( const slist_impl &x -, const slist_impl &y) -#endif -{ - typedef slist_impl slist_type; - const bool C = slist_type::constant_time_size; - if(C && x.size() != y.size()){ - return false; - } - return ::boost::intrusive::algo_equal(x.cbegin(), x.cend(), y.cbegin(), y.cend()); -} - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator!= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const slist_impl &x, const slist_impl &y) -#else -( const slist_impl &x -, const slist_impl &y) -#endif -{ return !(x == y); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator> -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const slist_impl &x, const slist_impl &y) -#else -( const slist_impl &x -, const slist_impl &y) -#endif -{ return y < x; } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator<= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const slist_impl &x, const slist_impl &y) -#else -( const slist_impl &x -, const slist_impl &y) -#endif -{ return !(y < x); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator>= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const slist_impl &x, const slist_impl &y) -#else -( const slist_impl &x -, const slist_impl &y) -#endif -{ return !(x < y); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline void swap -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(slist_impl &x, slist_impl &y) -#else -( slist_impl &x -, slist_impl &y) -#endif -{ x.swap(y); } - //! Helper metafunction to define a \c slist that yields to the same type when the //! same options (either explicitly or implicitly) are used. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) diff --git a/include/boost/intrusive/splaytree.hpp b/include/boost/intrusive/splaytree.hpp index e3866aa..d959710 100644 --- a/include/boost/intrusive/splaytree.hpp +++ b/include/boost/intrusive/splaytree.hpp @@ -482,34 +482,24 @@ class splaytree_impl //! @copydoc ::boost::intrusive::bstree::rebalance_subtree iterator rebalance_subtree(iterator root); + + friend bool operator< (const splaytree_impl &x, const splaytree_impl &y); + + friend bool operator==(const splaytree_impl &x, const splaytree_impl &y); + + friend bool operator!= (const splaytree_impl &x, const splaytree_impl &y); + + friend bool operator>(const splaytree_impl &x, const splaytree_impl &y); + + friend bool operator<=(const splaytree_impl &x, const splaytree_impl &y); + + friend bool operator>=(const splaytree_impl &x, const splaytree_impl &y); + + friend void swap(splaytree_impl &x, splaytree_impl &y); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) - -template -bool operator< (const splaytree_impl &x, const splaytree_impl &y); - -template -bool operator==(const splaytree_impl &x, const splaytree_impl &y); - -template -bool operator!= (const splaytree_impl &x, const splaytree_impl &y); - -template -bool operator>(const splaytree_impl &x, const splaytree_impl &y); - -template -bool operator<=(const splaytree_impl &x, const splaytree_impl &y); - -template -bool operator>=(const splaytree_impl &x, const splaytree_impl &y); - -template -void swap(splaytree_impl &x, splaytree_impl &y); - -#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) - //! Helper metafunction to define a \c splaytree that yields to the same type when the //! same options (either explicitly or implicitly) are used. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) diff --git a/include/boost/intrusive/treap.hpp b/include/boost/intrusive/treap.hpp index bf37469..d7f1458 100644 --- a/include/boost/intrusive/treap.hpp +++ b/include/boost/intrusive/treap.hpp @@ -774,11 +774,9 @@ class treap_impl //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. template - size_type erase(const KeyType& key, KeyValueCompare comp - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) + BOOST_INTRUSIVE_DOC1ST(size_type + , typename detail::disable_if_convertible::type) + erase(const KeyType& key, KeyValueCompare comp) { std::pair p = this->equal_range(key, comp); size_type n; @@ -867,11 +865,9 @@ class treap_impl //! Note: Invalidates the iterators //! to the erased elements. template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) + BOOST_INTRUSIVE_DOC1ST(size_type + , typename detail::disable_if_convertible::type) + erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer) { std::pair p = this->equal_range(key, comp); size_type n; @@ -1030,6 +1026,20 @@ class treap_impl //! @copydoc ::boost::intrusive::bstree::remove_node void remove_node(reference value); + friend bool operator< (const treap_impl &x, const treap_impl &y); + + friend bool operator==(const treap_impl &x, const treap_impl &y); + + friend bool operator!= (const treap_impl &x, const treap_impl &y); + + friend bool operator>(const treap_impl &x, const treap_impl &y); + + friend bool operator<=(const treap_impl &x, const treap_impl &y); + + friend bool operator>=(const treap_impl &x, const treap_impl &y); + + friend void swap(treap_impl &x, treap_impl &y); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED /// @cond @@ -1051,30 +1061,6 @@ class treap_impl /// @endcond }; -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) - -template -bool operator< (const treap_impl &x, const treap_impl &y); - -template -bool operator==(const treap_impl &x, const treap_impl &y); - -template -bool operator!= (const treap_impl &x, const treap_impl &y); - -template -bool operator>(const treap_impl &x, const treap_impl &y); - -template -bool operator<=(const treap_impl &x, const treap_impl &y); - -template -bool operator>=(const treap_impl &x, const treap_impl &y); - -template -void swap(treap_impl &x, treap_impl &y); - -#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Helper metafunction to define a \c treap that yields to the same type when the //! same options (either explicitly or implicitly) are used. diff --git a/include/boost/intrusive/unordered_set.hpp b/include/boost/intrusive/unordered_set.hpp index 4b0c91e..bce2bbe 100644 --- a/include/boost/intrusive/unordered_set.hpp +++ b/include/boost/intrusive/unordered_set.hpp @@ -473,11 +473,9 @@ class unordered_set_impl //! Note: Invalidates the iterators //! to the erased elements. template - void erase_and_dispose(const_iterator i, Disposer disposer - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) + BOOST_INTRUSIVE_DOC1ST(void + , typename detail::disable_if_convertible::type) + erase_and_dispose(const_iterator i, Disposer disposer) { table_type::erase_and_dispose(i, disposer); } //! Requires: Disposer::operator()(pointer) shouldn't throw. @@ -1503,19 +1501,11 @@ class unordered_multiset_impl //! Note: Invalidates the iterators //! to the erased elements. template - void erase_and_dispose(const_iterator i, Disposer disposer - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) + BOOST_INTRUSIVE_DOC1ST(void + , typename detail::disable_if_convertible::type) + erase_and_dispose(const_iterator i, Disposer disposer) { table_type::erase_and_dispose(i, disposer); } - #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) - template - void erase_and_dispose(const_iterator i, Disposer disposer) - { this->erase_and_dispose(const_iterator(i), disposer); } - #endif - //! Requires: Disposer::operator()(pointer) shouldn't throw. //! //! Effects: Erases the range pointed to by b end e. diff --git a/proj/vc7ide/Intrusive.sln b/proj/vc7ide/Intrusive.sln index 8ef1fc3..03b1e17 100644 --- a/proj/vc7ide/Intrusive.sln +++ b/proj/vc7ide/Intrusive.sln @@ -127,10 +127,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "null_iterator", "null_itera ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "map_test", "..\..\..\container\proj\vc7ide\map_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792606}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject Global GlobalSection(SolutionConfiguration) = preSolution Debug = Debug @@ -267,10 +263,6 @@ Global {32A79B10-B2A0-C1B8-9458-9456152413B5}.Debug.Build.0 = Debug|Win32 {32A79B10-B2A0-C1B8-9458-9456152413B5}.Release.ActiveCfg = Release|Win32 {32A79B10-B2A0-C1B8-9458-9456152413B5}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792606}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792606}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792606}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792606}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection diff --git a/test/bounded_pointer.hpp b/test/bounded_pointer.hpp index b6d568a..f20f100 100644 --- a/test/bounded_pointer.hpp +++ b/test/bounded_pointer.hpp @@ -54,8 +54,8 @@ class bounded_pointer {} template - bounded_pointer(const bounded_pointer &other, typename boost::intrusive::detail::enable_if_c - ::value>::type* = 0) + bounded_pointer( const bounded_pointer &other + , typename boost::intrusive::detail::enable_if_convertible::type* = 0) : m_offset(other.m_offset) {} @@ -63,8 +63,7 @@ class bounded_pointer { m_offset = other.m_offset; return *this; } template - typename boost::intrusive::detail::enable_if_c - ::value, bounded_pointer&>::type + typename boost::intrusive::detail::enable_if_convertible::type operator= (const bounded_pointer & other) { m_offset = other.m_offset; return *this; } @@ -172,15 +171,14 @@ class bounded_reference { assert(m_offset != max_offset); raw() = rhs.raw(); return *this; } template - bounded_reference(const bounded_reference &other, typename boost::intrusive::detail::enable_if_c - ::value>::type* = 0) + bounded_reference( const bounded_reference &other + , typename boost::intrusive::detail::enable_if_convertible::type* = 0) : m_offset(other.m_offset) {} template - typename boost::intrusive::detail::enable_if_c - ::value, bounded_reference&>::type - operator= (const bounded_reference & other) + typename boost::intrusive::detail::enable_if_convertible::type + operator= (const bounded_reference & other) { m_offset = other.m_offset; return *this; } friend std::ostream& operator << (std::ostream& os, const bounded_reference< T >& ref) diff --git a/test/test_container.hpp b/test/test_container.hpp index 7872101..712406c 100644 --- a/test/test_container.hpp +++ b/test/test_container.hpp @@ -76,6 +76,15 @@ void test_container( Container & c ) BOOST_TEST( c.size() == i ); } static_cast(c).check(); + //Very basic test for comparisons + { + BOOST_TEST(c == c); + BOOST_TEST(!(c != c)); + BOOST_TEST(!(c < c)); + BOOST_TEST(c <= c); + BOOST_TEST(!(c > c)); + BOOST_TEST(c >= c); + } }