Section: 22.10 [function.objects] Status: C++14 Submitter: Scott Meyers Opened: 2012-02-15 Last modified: 2016-01-28
Priority: Not Prioritized
View all other issues in [function.objects].
View all issues with C++14 status.
Discussion:
22.10 [function.objects] p5 says:
To enable adaptors and other components to manipulate function objects that take one or two arguments it is required that the function objects correspondingly provide typedefs
argument_type
andresult_type
for function objects that take one argument andfirst_argument_type
,second_argument_type
, andresult_type
for function objects that take two arguments.
I have two concerns about this paragraph. First, the wording appears to prescribe a requirement for all
function objects in valid C++ programs, but it seems unlikely that that is the intent. As such, the scope
of the requirement is unclear. For example, there is no mention of these typedefs in the specification for
closures (5.1.2), and Daniel Krügler has explained in the thread at
http://tinyurl.com/856plkn that conforming implementations can
detect the difference between closures with and without these typedefs. (Neither gcc 4.6 nor VC10 appear
to define typedefs such as result_type
for closure types. I have not tested other compilers.)
std::bind
, as Howard Hinnant explains in the thread at http://tinyurl.com/6q5bos4.
From what I can tell, the standard already defines which adaptability typedefs must be provided by various
kinds of function objects in the specifications for those objects. Examples include the function objects
specified in 22.10.6 [refwrap]- [negators]. I therefore suggest that
22.10 [function.objects]/5 simply be removed from the standard. I don't think it adds anything
except opportunities for confusion.
[2012-10 Portland: Move to Open]
This wording caused confusion earlier in the week when reviewing Stefan's paper on greater<>
.
This phrasing sounds normative, but is actually descriptive but uses unfortunate wording.
The main reason this wording exists is to document the protocol required to support the legacy binders in Annex D.
Stefan points out that unary_negate
and binary_negate
have not been deprecated and rely
on this. He plans a paper to remove this dependency.
Consensus that this wording is inadequate, confusing, and probably should be removed. However, that leaves a big hole in the specification for the legacy binders, that needs filling.
While not opposed to striking this paragraph, we will need the additional wording to fix the openning hole before this issue can move forward.
[ 2013-04-14 STL provides rationale ]
Rationale:
I've concluded that Scott's original proposed resolution was correct and complete. There are two sides to this story: the producers and the consumers of these typedefs.
Producers: As Scott noted, the Standard clearly documents which function objects must provide these
typedefs. Some function objects must provide them unconditionally (e.g. plus<T>
(for T != void
),
22.10.7 [arithmetic.operations]/1), some conditionally (e.g. reference_wrapper<T>
,
22.10.6 [refwrap]/2-4), and some don't have to provide them at all (e.g. lambdas, 7.5.6 [expr.prim.lambda]).
These requirements are clear, so we shouldn't change them or even add informative notes. Furthermore, because these
typedefs aren't needed in the C++11 world with decltype
/perfect forwarding/etc., we shouldn't add more
requirements to provide them.
Consumers: This is what we were concerned about at Portland. However, the consumers also clearly document
their requirements in the existing text. For example, reference_wrapper<T>
is also a conditional consumer,
and 22.10.6 [refwrap] explains what typedefs it's looking for. We were especially concerned about the old negators
and the deprecated binders, but they're okay too. [negators] clearly says that
unary_negate<Predicate>
requires Predicate::argument_type
to be a type, and
binary_negate<Predicate>
requires Predicate::first_argument_type
and Predicate::second_argument_type
to be types. (unary_negate
/binary_negate
provide result_type
but they don't consume it.)
99 [depr.lib.binders] behaves the same way with Fn::first_argument_type
, Fn::second_argument_type
,
and Fn::result_type
. No additional wording is necessary.
A careful reading of 22.10 [function.objects]/5 reveals that it wasn't talking about anything beyond the mere
existence of the mentioned typedefs — for example, it didn't mention that the function object's return type should be
result_type
, or even convertible to result_type
. As the producers and consumers are certainly talking about
the existence of the typedefs (in addition to clearly implying semantic requirements), we lose nothing by deleting the
unnecessary paragraph.
[2013-04-18, Bristol]
Previous wording:
Remove 22.10 [function.objects] p5:
To enable adaptors and other components to manipulate function objects that take one or two arguments it is required that the function objects correspondingly provide typedefsargument_type
andresult_type
for function objects that take one argument andfirst_argument_type
,second_argument_type
, andresult_type
for function objects that take two arguments.
Proposed resolution:
This wording is relative to N3485.
Edit 22.10 [function.objects] p5:
[Note:To enable adaptors and other components to manipulate function objects that take one or two arguments
it is required that the function objectsmany of the function objects in this clause correspondingly provide typedefsargument_type
andresult_type
for function objects that take one argument andfirst_argument_type
,second_argument_type
, andresult_type
for function objects that take two arguments.— end note]