From d5aede745eaf817da839ccd6a0f8409607f86e56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Fri, 26 May 2017 22:31:26 +0200 Subject: [PATCH] Unify std::binders and lambdas with custom binders --- doc/container.qbk | 2 + include/boost/container/detail/algorithm.hpp | 122 +++++++++++++++++++ include/boost/container/string.hpp | 64 ++++------ test/map_test.hpp | 4 +- test/set_test.hpp | 6 +- 5 files changed, 151 insertions(+), 47 deletions(-) diff --git a/doc/container.qbk b/doc/container.qbk index b0cd4bc..ebb1a49 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1218,9 +1218,11 @@ use [*Boost.Container]? There are several reasons for that: * Implemented `extract_sequence`, `adopt_sequence` functions for flat_[multi]map/set associative containers. * Fixed bugs: + * [@https://github.com/boostorg/container/pull/48 GitHub #48: ['"Replace deprecated/removed C++98 binders"]]. * [@https://github.com/boostorg/container/pull/49 GitHub #49: ['"Remove useless allocator copy in map"]]. * [@https://github.com/boostorg/container/pull/50 GitHub #50: ['"Fixed bug Trac #13038"]]. + [endsect] [section:release_notes_boost_1_64_00 Boost 1.64 Release] diff --git a/include/boost/container/detail/algorithm.hpp b/include/boost/container/detail/algorithm.hpp index 67e7876..1184422 100644 --- a/include/boost/container/detail/algorithm.hpp +++ b/include/boost/container/detail/algorithm.hpp @@ -29,6 +29,128 @@ namespace container { using boost::intrusive::algo_equal; using boost::intrusive::algo_lexicographical_compare; +template +class binder1st +{ + public: + typedef typename Func::second_argument_type argument_type; + typedef typename Func::result_type result_type; + + binder1st(const Func& func, const typename Func::first_argument_type& arg) + : op(func), value(arg) + {} + + result_type operator()(const argument_type& arg) const + { return op(value, arg); } + + result_type operator()(argument_type& arg) const + { return op(value, arg); } + + private: + Func op; + typename Func::first_argument_type value; +}; + +template +inline binder1st bind1st(const Func& func, const T& arg) +{ return boost::container::binder1st(func, arg); } + +template +class binder2nd +{ + public: + typedef typename Func::first_argument_type argument_type; + typedef typename Func::result_type result_type; + + binder2nd(const Func& func, const typename Func::second_argument_type& arg) + : op(func), value(arg) + {} + + result_type operator()(const argument_type& arg) const + { return op(arg, value); } + + result_type operator()(argument_type& arg) const + { return op(arg, value); } + + private: + Func op; + typename Func::second_argument_type value; +}; + +template +inline binder2nd bind2nd(const Func& func, const T& arg) +{ + return (boost::container::binder2nd(func, arg)); +} + +template +class unary_negate +{ + public: + typedef typename Func::argument_type argument_type; + typedef typename Func::result_type result_type; + + explicit unary_negate(const Func& func) + : m_func(func) + {} + + bool operator()(const typename Func::argument_type& arg) const + { return !m_func(arg); } + + private: + Func m_func; +}; + +template inline +unary_negate not1(const Func& func) +{ + return boost::container::unary_negate(func); +} + +template +InputIt find_if(InputIt first, InputIt last, UnaryPredicate p) +{ + for (; first != last; ++first) { + if (p(*first)) { + return first; + } + } + return last; +} + +template +InputIt find_first_of(InputIt first1, InputIt last1, ForwardIt first2, ForwardIt last2, BinaryPredicate p) +{ + for (; first1 != last1; ++first1) { + for (ForwardIt it = first2; it != last2; ++it) { + if (p(*first1, *it)) { + return first1; + } + } + } + return last1; +} + +template +ForwardIt1 search(ForwardIt1 first1, ForwardIt1 last1, + ForwardIt2 first2, ForwardIt2 last2, BinaryPredicate p) +{ + for (; ; ++first1) { + ForwardIt1 it = first1; + for (ForwardIt2 it2 = first2; ; ++it, ++it2) { + if (it2 == last2) { + return first1; + } + if (it == last1) { + return last1; + } + if (!p(*it, *it2)) { + break; + } + } + } +} + } //namespace container { } //namespace boost { diff --git a/include/boost/container/string.hpp b/include/boost/container/string.hpp index da4136d..2405678 100644 --- a/include/boost/container/string.hpp +++ b/include/boost/container/string.hpp @@ -39,6 +39,7 @@ #include #include #include +#include #include @@ -51,7 +52,6 @@ #include #include -#include //bind2nd, etc. #include #include #include @@ -541,12 +541,8 @@ class basic_string bool operator()(const typename Tr::char_type& x) const { - return std::find_if(m_first, m_last, -#ifdef BOOST_NO_CXX98_BINDERS - [&](argument_type ch) { return Eq_traits()(x, ch); }) == m_last; -#else - std::bind1st(Eq_traits(), x)) == m_last; -#endif + return boost::container::find_if(m_first, m_last, + boost::container::bind1st(Eq_traits(), x)) == m_last; } }; #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED @@ -2276,7 +2272,7 @@ class basic_string const pointer addr = this->priv_addr(); pointer finish = addr + this->priv_size(); const const_iterator result = - std::search(boost::movelib::to_raw_pointer(addr + pos), + boost::container::search(boost::movelib::to_raw_pointer(addr + pos), boost::movelib::to_raw_pointer(finish), s, s + n, Eq_traits()); return result != finish ? result - begin() : npos; @@ -2303,12 +2299,8 @@ class basic_string const pointer addr = this->priv_addr(); pointer finish = addr + sz; const const_iterator result = - std::find_if(addr + pos, finish, -#ifdef BOOST_NO_CXX98_BINDERS - [&](value_type ch) { return Eq_traits()(ch, c); }); -#else - std::bind2nd(Eq_traits(), c)); -#endif + boost::container::find_if(addr + pos, finish, + boost::container::bind2nd(Eq_traits(), c)); return result != finish ? result - begin() : npos; } } @@ -2379,12 +2371,8 @@ class basic_string else { const const_iterator last = begin() + container_detail::min_value(len - 1, pos) + 1; const_reverse_iterator rresult = - std::find_if(const_reverse_iterator(last), rend(), -#ifdef BOOST_NO_CXX98_BINDERS - [&](value_type ch) { return Eq_traits()(ch, c); }); -#else - std::bind2nd(Eq_traits(), c)); -#endif + boost::container::find_if(const_reverse_iterator(last), rend(), + boost::container::bind2nd(Eq_traits(), c)); return rresult != rend() ? (rresult.base() - 1) - begin() : npos; } } @@ -2397,7 +2385,7 @@ class basic_string //! //! Returns: xpos if the function can determine such a value for xpos. Otherwise, returns npos. size_type find_first_of(const basic_string& str, size_type pos = 0) const - { return find_first_of(str.c_str(), pos, str.size()); } + { return this->find_first_of(str.c_str(), pos, str.size()); } //! Effects: Determines the lowest position xpos, if possible, such that both of the //! following conditions obtain: a) pos <= xpos and xpos < size(); @@ -2408,7 +2396,7 @@ class basic_string //! Returns: xpos if the function can determine such a value for xpos. Otherwise, returns npos. template