// ------------------------------------------------------------------------------ // 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: functional.hpp 36246 2006-12-02 14:17:26Z andreas_huber69 $ // ------------------------------------------------------------------------------ #ifndef BOOST_FUNCTIONAL_HPP #define BOOST_FUNCTIONAL_HPP #include <boost/config.hpp> #include <boost/call_traits.hpp> #include <functional> namespace boost { #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 <class Operation> struct unary_traits_imp; template <class Operation> struct unary_traits_imp<Operation*> { 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 <class R, class A> struct unary_traits_imp<R(*)(A)> { typedef R (*function_type)(A); typedef R (*param_type)(A); typedef R result_type; typedef A argument_type; }; template <class Operation> struct binary_traits_imp; template <class Operation> struct binary_traits_imp<Operation*> { 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 <class R, class A1, class A2> struct binary_traits_imp<R(*)(A1,A2)> { 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 <class Operation> struct unary_traits { typedef typename detail::unary_traits_imp<Operation*>::function_type function_type; typedef typename detail::unary_traits_imp<Operation*>::param_type param_type; typedef typename detail::unary_traits_imp<Operation*>::result_type result_type; typedef typename detail::unary_traits_imp<Operation*>::argument_type argument_type; }; template <class R, class A> struct unary_traits<R(*)(A)> { typedef R (*function_type)(A); typedef R (*param_type)(A); typedef R result_type; typedef A argument_type; }; template <class Operation> struct binary_traits { typedef typename detail::binary_traits_imp<Operation*>::function_type function_type; typedef typename detail::binary_traits_imp<Operation*>::param_type param_type; typedef typename detail::binary_traits_imp<Operation*>::result_type result_type; typedef typename detail::binary_traits_imp<Operation*>::first_argument_type first_argument_type; typedef typename detail::binary_traits_imp<Operation*>::second_argument_type second_argument_type; }; template <class R, class A1, class A2> struct binary_traits<R(*)(A1,A2)> { 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 <class Operation> 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 <class Operation> 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 Predicate> class unary_negate : public std::unary_function<typename unary_traits<Predicate>::argument_type,bool> { public: explicit unary_negate(typename unary_traits<Predicate>::param_type x) : pred(x) {} bool operator()(typename call_traits<typename unary_traits<Predicate>::argument_type>::param_type x) const { return !pred(x); } private: typename unary_traits<Predicate>::function_type pred; }; template <class Predicate> unary_negate<Predicate> 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<Predicate>((typename unary_traits<Predicate>::param_type)pred); } template <class Predicate> unary_negate<Predicate> not1(Predicate &pred) { return unary_negate<Predicate>(pred); } // -------------------------------------------------------------------------- // binary_negate, not2 // -------------------------------------------------------------------------- template <class Predicate> class binary_negate : public std::binary_function<typename binary_traits<Predicate>::first_argument_type, typename binary_traits<Predicate>::second_argument_type, bool> { public: explicit binary_negate(typename binary_traits<Predicate>::param_type x) : pred(x) {} bool operator()(typename call_traits<typename binary_traits<Predicate>::first_argument_type>::param_type x, typename call_traits<typename binary_traits<Predicate>::second_argument_type>::param_type y) const { return !pred(x,y); } private: typename binary_traits<Predicate>::function_type pred; }; template <class Predicate> binary_negate<Predicate> 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<Predicate>((typename binary_traits<Predicate>::param_type)pred); } template <class Predicate> binary_negate<Predicate> not2(Predicate &pred) { return binary_negate<Predicate>(pred); } // -------------------------------------------------------------------------- // binder1st, bind1st // -------------------------------------------------------------------------- template <class Operation> class binder1st : public std::unary_function<typename binary_traits<Operation>::second_argument_type, typename binary_traits<Operation>::result_type> { public: binder1st(typename binary_traits<Operation>::param_type x, typename call_traits<typename binary_traits<Operation>::first_argument_type>::param_type y) : op(x), value(y) {} typename binary_traits<Operation>::result_type operator()(typename call_traits<typename binary_traits<Operation>::second_argument_type>::param_type x) const { return op(value, x); } protected: typename binary_traits<Operation>::function_type op; typename binary_traits<Operation>::first_argument_type value; }; template <class Operation> inline binder1st<Operation> bind1st(const Operation &op, typename call_traits< typename binary_traits<Operation>::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<Operation>((typename binary_traits<Operation>::param_type)op, x); } template <class Operation> inline binder1st<Operation> bind1st(Operation &op, typename call_traits< typename binary_traits<Operation>::first_argument_type >::param_type x) { return binder1st<Operation>(op, x); } // -------------------------------------------------------------------------- // binder2nd, bind2nd // -------------------------------------------------------------------------- template <class Operation> class binder2nd : public std::unary_function<typename binary_traits<Operation>::first_argument_type, typename binary_traits<Operation>::result_type> { public: binder2nd(typename binary_traits<Operation>::param_type x, typename call_traits<typename binary_traits<Operation>::second_argument_type>::param_type y) : op(x), value(y) {} typename binary_traits<Operation>::result_type operator()(typename call_traits<typename binary_traits<Operation>::first_argument_type>::param_type x) const { return op(x, value); } protected: typename binary_traits<Operation>::function_type op; typename binary_traits<Operation>::second_argument_type value; }; template <class Operation> inline binder2nd<Operation> bind2nd(const Operation &op, typename call_traits< typename binary_traits<Operation>::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<Operation>((typename binary_traits<Operation>::param_type)op, x); } template <class Operation> inline binder2nd<Operation> bind2nd(Operation &op, typename call_traits< typename binary_traits<Operation>::second_argument_type >::param_type x) { return binder2nd<Operation>(op, x); } // -------------------------------------------------------------------------- // mem_fun, etc // -------------------------------------------------------------------------- template <class S, class T> class mem_fun_t : public std::unary_function<T*, S> { public: explicit mem_fun_t(S (T::*p)()) : ptr(p) {} S operator()(T* p) const { return (p->*ptr)(); } private: S (T::*ptr)(); }; template <class S, class T, class A> class mem_fun1_t : public std::binary_function<T*, A, S> { public: explicit mem_fun1_t(S (T::*p)(A)) : ptr(p) {} S operator()(T* p, typename call_traits<A>::param_type x) const { return (p->*ptr)(x); } private: S (T::*ptr)(A); }; template <class S, class T> class const_mem_fun_t : public std::unary_function<const T*, S> { 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 S, class T, class A> class const_mem_fun1_t : public std::binary_function<const T*, A, S> { public: explicit const_mem_fun1_t(S (T::*p)(A) const) : ptr(p) {} S operator()(const T* p, typename call_traits<A>::param_type x) const { return (p->*ptr)(x); } private: S (T::*ptr)(A) const; }; template<class S, class T> inline mem_fun_t<S,T> mem_fun(S (T::*f)()) { return mem_fun_t<S,T>(f); } template<class S, class T, class A> inline mem_fun1_t<S,T,A> mem_fun(S (T::*f)(A)) { return mem_fun1_t<S,T,A>(f); } #ifndef BOOST_NO_POINTER_TO_MEMBER_CONST template<class S, class T> inline const_mem_fun_t<S,T> mem_fun(S (T::*f)() const) { return const_mem_fun_t<S,T>(f); } template<class S, class T, class A> inline const_mem_fun1_t<S,T,A> mem_fun(S (T::*f)(A) const) { return const_mem_fun1_t<S,T,A>(f); } #endif // BOOST_NO_POINTER_TO_MEMBER_CONST // -------------------------------------------------------------------------- // mem_fun_ref, etc // -------------------------------------------------------------------------- template <class S, class T> class mem_fun_ref_t : public std::unary_function<T&, S> { 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 S, class T, class A> class mem_fun1_ref_t : public std::binary_function<T&, A, S> { public: explicit mem_fun1_ref_t(S (T::*p)(A)) : ptr(p) {} S operator()(T& p, typename call_traits<A>::param_type x) const { return (p.*ptr)(x); } private: S (T::*ptr)(A); }; template <class S, class T> class const_mem_fun_ref_t : public std::unary_function<const T&, S> { 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 S, class T, class A> class const_mem_fun1_ref_t : public std::binary_function<const T&, A, S> { public: explicit const_mem_fun1_ref_t(S (T::*p)(A) const) : ptr(p) {} S operator()(const T& p, typename call_traits<A>::param_type x) const { return (p.*ptr)(x); } private: S (T::*ptr)(A) const; }; template<class S, class T> inline mem_fun_ref_t<S,T> mem_fun_ref(S (T::*f)()) { return mem_fun_ref_t<S,T>(f); } template<class S, class T, class A> inline mem_fun1_ref_t<S,T,A> mem_fun_ref(S (T::*f)(A)) { return mem_fun1_ref_t<S,T,A>(f); } #ifndef BOOST_NO_POINTER_TO_MEMBER_CONST template<class S, class T> inline const_mem_fun_ref_t<S,T> mem_fun_ref(S (T::*f)() const) { return const_mem_fun_ref_t<S,T>(f); } template<class S, class T, class A> inline const_mem_fun1_ref_t<S,T,A> mem_fun_ref(S (T::*f)(A) const) { return const_mem_fun1_ref_t<S,T,A>(f); } #endif // BOOST_NO_POINTER_TO_MEMBER_CONST // -------------------------------------------------------------------------- // ptr_fun // -------------------------------------------------------------------------- template <class Arg, class Result> class pointer_to_unary_function : public std::unary_function<Arg,Result> { public: explicit pointer_to_unary_function(Result (*f)(Arg)) : func(f) {} Result operator()(typename call_traits<Arg>::param_type x) const { return func(x); } private: Result (*func)(Arg); }; template <class Arg, class Result> inline pointer_to_unary_function<Arg,Result> ptr_fun(Result (*f)(Arg)) { return pointer_to_unary_function<Arg,Result>(f); } template <class Arg1, class Arg2, class Result> class pointer_to_binary_function : public std::binary_function<Arg1,Arg2,Result> { public: explicit pointer_to_binary_function(Result (*f)(Arg1, Arg2)) : func(f) {} Result operator()(typename call_traits<Arg1>::param_type x, typename call_traits<Arg2>::param_type y) const { return func(x,y); } private: Result (*func)(Arg1, Arg2); }; template <class Arg1, class Arg2, class Result> inline pointer_to_binary_function<Arg1,Arg2,Result> ptr_fun(Result (*f)(Arg1, Arg2)) { return pointer_to_binary_function<Arg1,Arg2,Result>(f); } } // namespace boost #endif