| Document number: | N4076 | |
|---|---|---|
| Date: | 2014-06-17 | |
| Project: | Programming Language C++, Library Working Group | |
| Reply-to: | Tomasz Kamiński <tomaszkam at gmail dot com> |
This proposal is to add function template not_fn that will allow to create negator of any callable object.
Changes since N4022:
argument_type, first_argument_type and second_argument_type
to match resolution of LWG issue #2387.fn to forwarding call wrapper.decay<F>::type with decay_t<F>.Changes since N3800:
Changes since N3699:
not_fn to allow wrapping of move-only types.The standard negators not1 and not2 accept only unary and binary functors
that define argument_type or first_argument_type and second_argument_type respectively,
which make them unusable with results of standard library functions such as bind and mem_fn.
Furthermore, with relation to N3421,
they cannot be used with new operator functor specializations.
This proposal addresses the problem by introducing a template function not_fn that returns complement of arbitrary predicate.
While the polymorphic lambda expressions (N3649) may be used to negate arbitrary functor, the proposed function offers more compact syntax:
std::partition(v.begin(), v.end(), [f](auto& p) { return !f(p); });
std::partition(v.begin(), v.end(), std::not_fn(f));
Furthermore, the use of lambda expression requires separate treatment of member pointers:
std::partition(v.begin(), v.end(), [pm](auto& p) { return !std::mem_fn(pm)(p); });
std::partition(v.begin(), v.end(), std::not_fn(pm));
With the incorporation of proposed functionality the old standard negators should be deprecated.
unary_negate, binary_negateProblem addressed by this paper may be solved by introducing perfect forwarding specializations of unary_negate and
binary_negate for types that do not define argument_type and first_argument_type,
second_argument_type nested types respectively, without
breaking existing code.
Although this solution does not address functions with arbitrary
number of arguments and requires additional implementation burden.
The perfect forwarding of return type was chosen instead of hard-coded bool.
Similar argumentation to the one provided in N3421 applies.
In Rapperswil decided not to define this type.
The argument_type, first_argument_type and second_argument_type
nested types are required by implementation to be consistent with most of library functors,
that define these types where they are well defined for target callable type.
Furthermore it is increasing the amount of existing code that will remain valid after changing not1,
not2 to not_fn.
In Rapperswil decided not to define these types.
This proposal has no dependencies beyond a C++11 compiler and Standard Library implementation.
(It depends on perfect forwarding, decltype and trailing return types.)
Nothing depends on this proposal.
After the declaration of not2 in the section 20.9 [function.objects]/2 (Header <functional> synopsis), add:
// 20.9.9, negators template <class F> unspecified not_fn(F&& f);
After paragraph 20.9.8 Negators [negators], insert a new paragraph. (Chapter [bind] (Function template bind) becomes 20.9.?)
20.9.9 Function template
not_fn[not_fn]template <class F> unspecified not_fn(F&& f);
In the text that follows:
FDis the typedecay_t<F>,fdis an lvalue of typeFDconstructed fromstd::forward<F>(f),fnis a forwarding call wrapper created as a result ofnot_fn(f),- Requires:
is_constructible<FD, F>::valueshall betrue.fdshall be a callable object ([func.def] 20.9.1).- Returns:
A forwarding call wrapper
fnsuch that the expressionfn(a1, a2, ..., aN)is equivalent to!INVOKE(fd, a1, a2, ..., aN)([func.require] 20.9.2).- Throws:
Nothing unless the construction of
fdthrows an exception.- Remarks:
The return type shall satisfy the requirements of
MoveConstructible. IfFDsatisfies the requirements ofCopyConstructible, then the return type shall satisfy the requirements ofCopyConstructible. [ Note: This implies thatFDis MoveConstructible. — end note ][ Note: Function template
not_fncan usually provide a better solution than using the negatorsnot1andnot2. — end note ]
Anna Salwa originally proposed not_fn in discussion group ISO C++ Standard - Future Proposals.
Mateusz Kwiatkowski, Jonathan Wakely and Daniel Krügler offered many useful suggestions and corrections to the proposal.