This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++14 status.

### 2149. Concerns about 20.8/5

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` and `result_type` for function objects that take one argument and `first_argument_type`, `second_argument_type`, and `result_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.)

Second, the requirement appears to be unimplementable in some cases, notably for function objects returned from `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.5 [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 typedefs `argument_type` and `result_type` for function objects that take one argument and `first_argument_type`, `second_argument_type`, and `result_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 objects many of the function objects in this clause correspondingly provide typedefs `argument_type` and `result_type` for function objects that take one argument and `first_argument_type`, `second_argument_type`, and `result_type` for function objects that take two arguments.— end note]