src/boost/functional.hpp
60c84217
 // ------------------------------------------------------------------------------
 // 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