Addressed NB comments: GB 95
Addressed issues: LWG 1290, LWG 1279
This paper attempts to resolve issues related to several currently required class-derivation relations from specializations of unary_function and binary_function.
For details of the rationale of this paper see n3145.
During the Batavia 2010 meeting it was agreed on the general direction suggested by n3145. There was also one part of the proposal that did not reach consensus, namely the deprecation of the negators not1(), not2(), and their corresponding return types, because there are currently no actual replacement forms (except usage of lambda expressions).
This revision of n3145 does exclude this particular part, and adapts the current definitions of unary_negate and binary_negate in the same way as for the remaining affected function object types.
The proposed wording changes refer to N3126.
namespace std { //20.8.3[depr.lib.base], base (deprecated): template <class Arg, class Result> struct unary_function; template <class Arg1, class Arg2, class Result> struct binary_function; [..] // 20.8.9, negators: template <class Predicate> class unary_negate; template <class Predicate> unary_negate<Predicate> not1(const Predicate&); template <class Predicate> class binary_negate; template <class Predicate> binary_negate<Predicate> not2(const Predicate&); [..] //20.8.11[depr.lib.funptr.adaptors], adaptors (deprecated): template <class Arg, class Result> class pointer_to_unary_function; template <class Arg, class Result> pointer_to_unary_function<Arg,Result> ptr_fun(Result (*)(Arg)); template <class Arg1, class Arg2, class Result> class pointer_to_binary_function; template <class Arg1, class Arg2, class Result> pointer_to_binary_function<Arg1,Arg2,Result> ptr_fun(Result (*)(Arg1,Arg2)); //20.8.12[depr.lib.memptr.adaptors], adaptors (deprecated): template<class S, class T> class mem_fun_t; template<class S, class T, class A> class mem_fun1_t; template<class S, class T> mem_fun_t<S,T> mem_fun(S (T::*f)()); template<class S, class T, class A> mem_fun1_t<S,T,A> mem_fun(S (T::*f)(A)); template<class S, class T> class mem_fun_ref_t; template<class S, class T, class A> class mem_fun1_ref_t; template<class S, class T> mem_fun_ref_t<S,T> mem_fun_ref(S (T::*f)()); template<class S, class T, class A> mem_fun1_ref_t<S,T,A> mem_fun_ref(S (T::*f)(A)); template <class S, class T> class const_mem_fun_t; template <class S, class T, class A> class const_mem_fun1_t; template <class S, class T> const_mem_fun_t<S,T> mem_fun(S (T::*f)() const); template <class S, class T, class A> const_mem_fun1_t<S,T,A> mem_fun(S (T::*f)(A) const); template <class S, class T> class const_mem_fun_ref_t; template <class S, class T, class A> class const_mem_fun1_ref_t; template <class S, class T> const_mem_fun_ref_t<S,T> mem_fun_ref(S (T::*f)() const); template <class S, class T, class A> const_mem_fun1_ref_t<S,T,A> mem_fun_ref(S (T::*f)(A) const); [..] }
20.8.3 Base [base]
1 The following classes are provided to simplify the typedefs of the argument and result types:
namespace std { template <class Arg, class Result> struct unary_function { typedef Arg argument_type; typedef Result result_type; }; } namespace std { template <class Arg1, class Arg2, class Result> struct binary_function { typedef Arg1 first_argument_type; typedef Arg2 second_argument_type; typedef Result result_type; }; }
D.?? Base [depr.lib.base]
namespace std { template <class Arg, class Result> struct unary_function { typedef Arg argument_type; typedef Result result_type; }; } namespace std { template <class Arg1, class Arg2, class Result> struct binary_function { typedef Arg1 first_argument_type; typedef Arg2 second_argument_type; typedef Result result_type; }; }
namespace std { template <class T> class reference_wrapper: public unary_function<T1, R> // see below: public binary_function<T1, T2, R> // see below{ public : // types typedef T type; typedef see below result_type; // not always defined typedef see below argument_type; // not always defined typedef see below first_argument_type; // not always defined typedef see below second_argument_type; // not always defined // construct/copy/destroy [..] }; }
3 The template instantiation reference_wrapper<T> shall be derived from std::unary_function<T1, R>define
a nested type named argument_type as a synonym for T1 only if the type T is any of the following:
4 The template instantiation reference_wrapper<T> shall be derived from std::binary_function<T1, T2, R>define
two nested types named first_argument_type and second_argument_type as a synonym for T1 and T2,
respectively, only if the type T is any of the following:
template <class T> struct plus: binary_function<T,T,T>{ typedef T first_argument_type; typedef T second_argument_type; typedef T result_type; T operator()(const T& x, const T& y) const; }; [..] template <class T> struct minus: binary_function<T,T,T>{ typedef T first_argument_type; typedef T second_argument_type; typedef T result_type; T operator()(const T& x, const T& y) const; }; [..] template <class T> struct multiplies: binary_function<T,T,T>{ typedef T first_argument_type; typedef T second_argument_type; typedef T result_type; T operator()(const T& x, const T& y) const; }; [..] template <class T> struct divides: binary_function<T,T,T>{ typedef T first_argument_type; typedef T second_argument_type; typedef T result_type; T operator()(const T& x, const T& y) const; }; [..] template <class T> struct modulus: binary_function<T,T,T>{ typedef T first_argument_type; typedef T second_argument_type; typedef T result_type; T operator()(const T& x, const T& y) const; }; [..] template <class T> struct negate: unary_function<T,T>{ typedef T argument_type; typedef T result_type; T operator()(const T& x) const; };
template <class T> struct equal_to: binary_function<T,T,bool>{ typedef T first_argument_type; typedef T second_argument_type; typedef bool result_type; bool operator()(const T& x, const T& y) const; }; [..] template <class T> struct not_equal_to: binary_function<T,T,bool>{ typedef T first_argument_type; typedef T second_argument_type; typedef bool result_type; bool operator()(const T& x, const T& y) const; }; [..] template <class T> struct greater: binary_function<T,T,bool>{ typedef T first_argument_type; typedef T second_argument_type; typedef bool result_type; bool operator()(const T& x, const T& y) const; }; [..] template <class T> struct less: binary_function<T,T,bool>{ typedef T first_argument_type; typedef T second_argument_type; typedef bool result_type; bool operator()(const T& x, const T& y) const; }; [..] template <class T> struct greater_equal: binary_function<T,T,bool>{ typedef T first_argument_type; typedef T second_argument_type; typedef bool result_type; bool operator()(const T& x, const T& y) const; }; [..] template <class T> struct less_equal: binary_function<T,T,bool>{ typedef T first_argument_type; typedef T second_argument_type; typedef bool result_type; bool operator()(const T& x, const T& y) const; };
template <class T> struct logical_and: binary_function<T,T,bool>{ typedef T first_argument_type; typedef T second_argument_type; typedef bool result_type; bool operator()(const T& x, const T& y) const; }; [..] template <class T> struct logical_or: binary_function<T,T,bool>{ typedef T first_argument_type; typedef T second_argument_type; typedef bool result_type; bool operator()(const T& x, const T& y) const; }; [..] template <class T> struct logical_not: unary_function<T,bool>{ typedef T argument_type; typedef bool result_type; bool operator()(const T& x) const; };
template <class T> struct bit_and: binary_function<T,T,T>{ typedef T first_argument_type; typedef T second_argument_type; typedef T result_type; T operator()(const T& x, const T& y) const; }; [..] template <class T> struct bit_or: binary_function<T,T,T>{ typedef T first_argument_type; typedef T second_argument_type; typedef T result_type; T operator()(const T& x, const T& y) const; }; [..] template <class T> struct bit_xor: binary_function<T,T,T>{ typedef T first_argument_type; typedef T second_argument_type; typedef T result_type; T operator()(const T& x, const T& y) const; };
template <class Predicate> class unary_negate: public unary_function<typename Predicate::argument_type,bool>{ public: typedef typename Predicate::argument_type argument_type; typedef bool result_type; explicit unary_negate(const Predicate& pred); bool operator()(const typename Predicate::argument_type& x) const; }; [..] template <class Predicate> class binary_negate: public binary_function<typename Predicate::first_argument_type, typename Predicate::second_argument_type, bool>{ public: typedef typename Predicate::first_argument_type first_argument_type; typedef typename Predicate::second_argument_type second_argument_type; typedef bool result_type; explicit binary_negate(const Predicate& pred); bool operator()(const typename Predicate::first_argument_type& x, const typename Predicate::second_argument_type& y) const; };
D.?? Adaptors [depr.lib.adaptors]
The adaptors ptr_fun, mem_fun, mem_fun_ref, and their corresponding return types are deprecated. [ Note: The function template bind (20.8.10) provides a better solution. — end note ]
D.??.1 Adaptors for pointers to functions [depr.lib.funptr.adaptors]
1 To allow pointers to (unary and binary) functions to work with function adaptors the library provides:
template <class Arg, class Result> class pointer_to_unary_function : public unary_function<Arg, Result> {
[..] // Remaining parts from previous 20.8.11 Adaptors for pointers to functions [function.pointer.adaptors]
D.??.2 Adaptors for pointers to members [depr.lib.memptr.adaptors]
1 The purpose of the following is to provide the same facilities for pointer to members as those provided for pointers to functions in 20.8.11.:
template <class S, class T> class mem_fun_t : public unary_function<T*, S> {
[..] // Remaining parts from previous 20.8.12 Adaptors for pointers to members [member.pointer.adaptors]
2 The simple call wrapper shall be derived from std::unary_function<cv T*, Ret>define
two nested types named argument_type and result_type as a synonym for cv T* and Ret,
respectively, when pm is a pointer to member function with cv-qualifier cv and taking no arguments,
where Ret is pm's return type.
3 The simple call wrapper shall be derived from std::binary_function<cv T*, T1, Ret>define
three nested types named first_argument_type, second_argument_type, and result_type as a synonym for
cv T*, T1, and Ret, respectively, when pm is a pointer to member function
with cv-qualifier cv and taking one argument of type T1, where Ret is pm's return type.
namespace std { template<class> class function; // undefined template<class R, class... ArgTypes> class function<R(ArgTypes...)>: public unary_function<T1, R> // iff sizeof...(ArgTypes) == 1 and ArgTypes contains T1: public binary_function<T1, T2, R> // iff sizeof...(ArgTypes) == 2 and ArgTypes contains T1 and T2{ public: typedef R result_type; typedef T1 argument_type; // iff sizeof...(ArgTypes) == 1 and ArgTypes contains T1 typedef T1 first_argument_type; // iff sizeof...(ArgTypes) == 2 and ArgTypes contains T1 as first type typedef T2 second_argument_type; // iff sizeof...(ArgTypes) == 2 and ArgTypes contains T2 as second type // 20.8.14.2.1, construct/copy/destroy: [..]
1 The class template owner_less allows ownership-based mixed comparisons of shared and weak pointers.
namespace std { template<class T> struct owner_less; template<class T> struct owner_less<shared_ptr<T> >: binary_function<shared_ptr<T>, shared_ptr<T>, bool>{ typedef bool result_type; typedef shared_ptr<T> first_argument_type; typedef shared_ptr<T> second_argument_type; bool operator()(shared_ptr<T> const&, shared_ptr<T> const&) const; bool operator()(shared_ptr<T> const&, weak_ptr<T> const&) const; bool operator()(weak_ptr<T> const&, shared_ptr<T> const&) const; }; template<class T> struct owner_less<weak_ptr<T> >: binary_function<weak_ptr<T>, weak_ptr<T>, bool>{ typedef bool result_type; typedef weak_ptr<T> first_argument_type; typedef weak_ptr<T> second_argument_type; bool operator()(weak_ptr<T> const&, weak_ptr<T> const&) const; bool operator()(shared_ptr<T> const&, weak_ptr<T> const&) const; bool operator()(weak_ptr<T> const&, shared_ptr<T> const&) const; }; }
namespace std { template <class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key, T> > > class map { public: [..] class value_compare: public binary_function<value_type,value_type,bool>{ friend class map; protected: Compare comp; value_compare(Compare c) : comp(c) {} public: typedef value_type first_argument_type; typedef value_type second_argument_type; typedef bool result_type; bool operator()(const value_type& x, const value_type& y) const { return comp(x.first, y.first); } }; [..]
namespace std { template <class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key, T> > > class multimap { public: [..] class value_compare: public binary_function<value_type,value_type,bool>{ friend class multimap; protected: Compare comp; value_compare(Compare c) : comp(c) {} public: typedef value_type first_argument_type; typedef value_type second_argument_type; typedef bool result_type; bool operator()(const value_type& x, const value_type& y) const { return comp(x.first, y.first); } }; [..]