385. Does call by value imply the CopyConstructible requirement?

Section: 20 [library] Status: NAD Submitter: Matt Austern Opened: 2002-10-23 Last modified: 2016-02-10

Priority: Not Prioritized

View all other issues in [library].

View all issues with NAD status.

Discussion:

Many function templates have parameters that are passed by value; a typical example is find_if's pred parameter in 28.5.5 [alg.find]. Are the corresponding template parameters (Predicate in this case) implicitly required to be CopyConstructible, or does that need to be spelled out explicitly?

This isn't quite as silly a question as it might seem to be at first sight. If you call find_if in such a way that template argument deduction applies, then of course you'll get call by value and you need to provide a copy constructor. If you explicitly provide the template arguments, however, you can force call by reference by writing something like find_if<my_iterator, my_predicate&>. The question is whether implementation are required to accept this, or whether this is ill-formed because my_predicate& is not CopyConstructible.

The scope of this problem, if it is a problem, is unknown. Function object arguments to generic algorithms in clauses 28 [algorithms] and 29 [numerics] are obvious examples. A review of the whole library is necessary.

[ This is really two issues. First, predicates are typically passed by value but we don't say they must be Copy Constructible. They should be. Second: is specialization allowed to transform value arguments into references? References aren't copy constructible, so this should not be allowed. ]

[ 2007-01-12, Howard: First, despite the note above, references are copy constructible. They just aren't assignable. Second, this is very closely related to 92 and should be consistent with that. That issue already says that implementations are allowed to copy function objects. If one passes in a reference, it is copyable, but susceptible to slicing if one passes in a reference to a base. Third, with rvalue reference in the language one only needs to satisfy MoveConstructible to pass an rvalue "by value". Though the function might still copy the function object internally (requiring CopyConstructible). Finally (and fwiw), if we wanted to, it is easy to code all of the std::algorithms such that they do not copy function objects internally. One merely passes them by reference internally if desired (this has been fully implemented and shipped for several years). If this were mandated, it would reverse 92, allowing function objects to reliably maintain state. E.g. the example in 92 would reliably remove only the third element. ]

Proposed resolution:

Recommend NAD.

Rationale:

Generic algorithms will be marked with concepts and these will imply a requirement of MoveConstructible (not CopyConstructible). The signature of the function will then precisely describe and enforce the precise requirements.