Document number: | N3800 | |
---|---|---|
Date: | 2013-09-16 | |
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 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_negate
Problem 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.
The argument_type
, first_argument_type
and second_argument_type
nested types are required by implemenatation to be consistent with most of library functors,
that define these types where they are well defined for target callable type.
Futhermore it is increasing the amount of existing code that will remain valid after changing not1
,
not2
to not_fn
.
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.10 [function.objects]/2 (Header <functional>
synopsis), add:
// 20.10.9, negators template <class F> unspecified not_fn(F&& f);
After paragraph 20.10.8 Negators [negators], insert a new paragraph. (Chapter [bind] (Function template bind
) becomes 20.10.?)
20.10.9 Function template
not_fn
[not_fn]template <class F> unspecified not_fn(F&& f);
In the text that follows, the following names have the following meanings:
FD
is the typedecay<F>::type
,fd
is an lvalue of typeFD
constructed fromstd::forward<F>(f),
fn
is a simple call wrapper created as a result ofnot_fn(f)
,FN
is a type offn
,FW
is a type of forwarding call wrapper forf
with a weak result type ([func.require] 20.10.2).- Requires:
- is_constructible<FD, F>::value shall be
true
.f
shall be a callable object ([func.require] 20.10.2).- Returns:
A simple call wrapper
fn
such that the expressionfn(a1, a2, ..., aN)
is equivalent to!INVOKE(fd, a1, a2, ..., aN)
([func.require] 20.10.2).- Throws:
Nothing unless the construction of
fd
throws an exception.- Remarks:
The return type shall satisfy the requirements of
MoveConstructible
. IfFD
satisfy the requirements ofCopyConstructible
, then the return type shall satisfy the requirements ofCopyConstructible
. [ Note: This implies thatFD
is MoveConstructible. — end note ]The
FN
shall define a nested type namedresult_type
as a synonym toR
only ifFW
would have a nested typeresult_type
; the typeR
isdecltype(!declval<typename FW::result_type>())
.The
FN
shall define a nested type namedargument_type
as a synonym forT1
only if the typeF
is any of the following:
- a function type or a pointer to function type taking one argument of type
T1
- a pointer to member function
R T0::f() cv
(wherecv
represents the member function's cv-qualifiers); the typeT1
iscv T0*
- a class type with a member type
argument_type
; the typeT1
isF::argument_type.
.The
FN
shall define two nested types namedfirst_argument_type
andsecond_argument_type
as synonyms forT1
andT2
, respectively, only if the typeF
is any of the following:
- a function type or a pointer to function type taking two arguments of types
T1
andT2
- a pointer to member function
R T0::f(T2) cv
(wherecv
represents the member function's cv-qualifiers); the typeT1
iscv T0*
- a class type with member types
first_argument_type
andsecond_argument_type
; the typeT1
isF::first_argument_type
and the typeT2
isF::second_argument_type.
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.