// ------------------------------------------------------------------------------ // Copyright (c) 2000 Cadenza New Zealand Ltd // Distributed under the Boost Software License, Version 1.0. (See accompany- // ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // ------------------------------------------------------------------------------ // Boost functional.hpp header file // See http://www.boost.org/libs/functional for documentation. // ------------------------------------------------------------------------------ // $Id$ // ------------------------------------------------------------------------------ #ifndef BOOST_FUNCTIONAL_HPP #define BOOST_FUNCTIONAL_HPP #include #include #include namespace boost { namespace functional { namespace detail { // std::unary_function and std::binary_function were both removed // in C++17. template struct unary_function { typedef Arg1 argument_type; typedef Result result_type; }; template struct binary_function { typedef Arg1 first_argument_type; typedef Arg2 second_argument_type; typedef Result result_type; }; } } #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION // -------------------------------------------------------------------------- // The following traits classes allow us to avoid the need for ptr_fun // because the types of arguments and the result of a function can be // deduced. // // In addition to the standard types defined in unary_function and // binary_function, we add // // - function_type, the type of the function or function object itself. // // - param_type, the type that should be used for passing the function or // function object as an argument. // -------------------------------------------------------------------------- namespace detail { template struct unary_traits_imp; template struct unary_traits_imp { typedef Operation function_type; typedef const function_type & param_type; typedef typename Operation::result_type result_type; typedef typename Operation::argument_type argument_type; }; template struct unary_traits_imp { typedef R (*function_type)(A); typedef R (*param_type)(A); typedef R result_type; typedef A argument_type; }; template struct binary_traits_imp; template struct binary_traits_imp { typedef Operation function_type; typedef const function_type & param_type; typedef typename Operation::result_type result_type; typedef typename Operation::first_argument_type first_argument_type; typedef typename Operation::second_argument_type second_argument_type; }; template struct binary_traits_imp { typedef R (*function_type)(A1,A2); typedef R (*param_type)(A1,A2); typedef R result_type; typedef A1 first_argument_type; typedef A2 second_argument_type; }; } // namespace detail template struct unary_traits { typedef typename detail::unary_traits_imp::function_type function_type; typedef typename detail::unary_traits_imp::param_type param_type; typedef typename detail::unary_traits_imp::result_type result_type; typedef typename detail::unary_traits_imp::argument_type argument_type; }; template struct unary_traits { typedef R (*function_type)(A); typedef R (*param_type)(A); typedef R result_type; typedef A argument_type; }; template struct binary_traits { typedef typename detail::binary_traits_imp::function_type function_type; typedef typename detail::binary_traits_imp::param_type param_type; typedef typename detail::binary_traits_imp::result_type result_type; typedef typename detail::binary_traits_imp::first_argument_type first_argument_type; typedef typename detail::binary_traits_imp::second_argument_type second_argument_type; }; template struct binary_traits { typedef R (*function_type)(A1,A2); typedef R (*param_type)(A1,A2); typedef R result_type; typedef A1 first_argument_type; typedef A2 second_argument_type; }; #else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION // -------------------------------------------------------------------------- // If we have no partial specialisation available, decay to a situation // that is no worse than in the Standard, i.e., ptr_fun will be required. // -------------------------------------------------------------------------- template struct unary_traits { typedef Operation function_type; typedef const Operation& param_type; typedef typename Operation::result_type result_type; typedef typename Operation::argument_type argument_type; }; template struct binary_traits { typedef Operation function_type; typedef const Operation & param_type; typedef typename Operation::result_type result_type; typedef typename Operation::first_argument_type first_argument_type; typedef typename Operation::second_argument_type second_argument_type; }; #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION // -------------------------------------------------------------------------- // unary_negate, not1 // -------------------------------------------------------------------------- template class unary_negate : public boost::functional::detail::unary_function::argument_type,bool> { public: explicit unary_negate(typename unary_traits::param_type x) : pred(x) {} bool operator()(typename call_traits::argument_type>::param_type x) const { return !pred(x); } private: typename unary_traits::function_type pred; }; template unary_negate not1(const Predicate &pred) { // The cast is to placate Borland C++Builder in certain circumstances. // I don't think it should be necessary. return unary_negate((typename unary_traits::param_type)pred); } template unary_negate not1(Predicate &pred) { return unary_negate(pred); } // -------------------------------------------------------------------------- // binary_negate, not2 // -------------------------------------------------------------------------- template class binary_negate : public boost::functional::detail::binary_function< typename binary_traits::first_argument_type, typename binary_traits::second_argument_type, bool> { public: explicit binary_negate(typename binary_traits::param_type x) : pred(x) {} bool operator()(typename call_traits::first_argument_type>::param_type x, typename call_traits::second_argument_type>::param_type y) const { return !pred(x,y); } private: typename binary_traits::function_type pred; }; template binary_negate not2(const Predicate &pred) { // The cast is to placate Borland C++Builder in certain circumstances. // I don't think it should be necessary. return binary_negate((typename binary_traits::param_type)pred); } template binary_negate not2(Predicate &pred) { return binary_negate(pred); } // -------------------------------------------------------------------------- // binder1st, bind1st // -------------------------------------------------------------------------- template class binder1st : public boost::functional::detail::unary_function< typename binary_traits::second_argument_type, typename binary_traits::result_type> { public: binder1st(typename binary_traits::param_type x, typename call_traits::first_argument_type>::param_type y) : op(x), value(y) {} typename binary_traits::result_type operator()(typename call_traits::second_argument_type>::param_type x) const { return op(value, x); } protected: typename binary_traits::function_type op; typename binary_traits::first_argument_type value; }; template inline binder1st bind1st(const Operation &op, typename call_traits< typename binary_traits::first_argument_type >::param_type x) { // The cast is to placate Borland C++Builder in certain circumstances. // I don't think it should be necessary. return binder1st((typename binary_traits::param_type)op, x); } template inline binder1st bind1st(Operation &op, typename call_traits< typename binary_traits::first_argument_type >::param_type x) { return binder1st(op, x); } // -------------------------------------------------------------------------- // binder2nd, bind2nd // -------------------------------------------------------------------------- template class binder2nd : public boost::functional::detail::unary_function< typename binary_traits::first_argument_type, typename binary_traits::result_type> { public: binder2nd(typename binary_traits::param_type x, typename call_traits::second_argument_type>::param_type y) : op(x), value(y) {} typename binary_traits::result_type operator()(typename call_traits::first_argument_type>::param_type x) const { return op(x, value); } protected: typename binary_traits::function_type op; typename binary_traits::second_argument_type value; }; template inline binder2nd bind2nd(const Operation &op, typename call_traits< typename binary_traits::second_argument_type >::param_type x) { // The cast is to placate Borland C++Builder in certain circumstances. // I don't think it should be necessary. return binder2nd((typename binary_traits::param_type)op, x); } template inline binder2nd bind2nd(Operation &op, typename call_traits< typename binary_traits::second_argument_type >::param_type x) { return binder2nd(op, x); } // -------------------------------------------------------------------------- // mem_fun, etc // -------------------------------------------------------------------------- template class mem_fun_t : public boost::functional::detail::unary_function { public: explicit mem_fun_t(S (T::*p)()) : ptr(p) {} S operator()(T* p) const { return (p->*ptr)(); } private: S (T::*ptr)(); }; template class mem_fun1_t : public boost::functional::detail::binary_function { public: explicit mem_fun1_t(S (T::*p)(A)) : ptr(p) {} S operator()(T* p, typename call_traits::param_type x) const { return (p->*ptr)(x); } private: S (T::*ptr)(A); }; template class const_mem_fun_t : public boost::functional::detail::unary_function { public: explicit const_mem_fun_t(S (T::*p)() const) : ptr(p) {} S operator()(const T* p) const { return (p->*ptr)(); } private: S (T::*ptr)() const; }; template class const_mem_fun1_t : public boost::functional::detail::binary_function { public: explicit const_mem_fun1_t(S (T::*p)(A) const) : ptr(p) {} S operator()(const T* p, typename call_traits::param_type x) const { return (p->*ptr)(x); } private: S (T::*ptr)(A) const; }; template inline mem_fun_t mem_fun(S (T::*f)()) { return mem_fun_t(f); } template inline mem_fun1_t mem_fun(S (T::*f)(A)) { return mem_fun1_t(f); } #ifndef BOOST_NO_POINTER_TO_MEMBER_CONST template inline const_mem_fun_t mem_fun(S (T::*f)() const) { return const_mem_fun_t(f); } template inline const_mem_fun1_t mem_fun(S (T::*f)(A) const) { return const_mem_fun1_t(f); } #endif // BOOST_NO_POINTER_TO_MEMBER_CONST // -------------------------------------------------------------------------- // mem_fun_ref, etc // -------------------------------------------------------------------------- template class mem_fun_ref_t : public boost::functional::detail::unary_function { public: explicit mem_fun_ref_t(S (T::*p)()) : ptr(p) {} S operator()(T& p) const { return (p.*ptr)(); } private: S (T::*ptr)(); }; template class mem_fun1_ref_t : public boost::functional::detail::binary_function { public: explicit mem_fun1_ref_t(S (T::*p)(A)) : ptr(p) {} S operator()(T& p, typename call_traits::param_type x) const { return (p.*ptr)(x); } private: S (T::*ptr)(A); }; template class const_mem_fun_ref_t : public boost::functional::detail::unary_function { public: explicit const_mem_fun_ref_t(S (T::*p)() const) : ptr(p) {} S operator()(const T &p) const { return (p.*ptr)(); } private: S (T::*ptr)() const; }; template class const_mem_fun1_ref_t : public boost::functional::detail::binary_function { public: explicit const_mem_fun1_ref_t(S (T::*p)(A) const) : ptr(p) {} S operator()(const T& p, typename call_traits::param_type x) const { return (p.*ptr)(x); } private: S (T::*ptr)(A) const; }; template inline mem_fun_ref_t mem_fun_ref(S (T::*f)()) { return mem_fun_ref_t(f); } template inline mem_fun1_ref_t mem_fun_ref(S (T::*f)(A)) { return mem_fun1_ref_t(f); } #ifndef BOOST_NO_POINTER_TO_MEMBER_CONST template inline const_mem_fun_ref_t mem_fun_ref(S (T::*f)() const) { return const_mem_fun_ref_t(f); } template inline const_mem_fun1_ref_t mem_fun_ref(S (T::*f)(A) const) { return const_mem_fun1_ref_t(f); } #endif // BOOST_NO_POINTER_TO_MEMBER_CONST // -------------------------------------------------------------------------- // ptr_fun // -------------------------------------------------------------------------- template class pointer_to_unary_function : public boost::functional::detail::unary_function { public: explicit pointer_to_unary_function(Result (*f)(Arg)) : func(f) {} Result operator()(typename call_traits::param_type x) const { return func(x); } private: Result (*func)(Arg); }; template inline pointer_to_unary_function ptr_fun(Result (*f)(Arg)) { return pointer_to_unary_function(f); } template class pointer_to_binary_function : public boost::functional::detail::binary_function { public: explicit pointer_to_binary_function(Result (*f)(Arg1, Arg2)) : func(f) {} Result operator()(typename call_traits::param_type x, typename call_traits::param_type y) const { return func(x,y); } private: Result (*func)(Arg1, Arg2); }; template inline pointer_to_binary_function ptr_fun(Result (*f)(Arg1, Arg2)) { return pointer_to_binary_function(f); } } // namespace boost #endif