Created on 2020-10-31.00:00:00 last changed 40 months ago
Proposed resolution:
This wording is relative to N4868.
Modify [func.wrap.func.con] as indicated:
template<class F> function(F f);-8- Constraints: F is Lvalue-Callable ([func.wrap.func.general]) for argument types ArgTypes... and return type R, and is_copy_constructible_v<F> is true.
-9- Preconditions: F meets the Cpp17CopyConstructible requirements. […]
[ 2021-08-20; LWG telecon ]
LWG requested that the constraint cited above for
move_only_function
(né any_invocable
)
be moved to a Mandates: element instead, to avoid the same
constraint recursion.
[ 2021-05-17; Tim comments ]
The new constraint causes constraint recursion in an example like:
struct C { explicit C(std::function<void()>); // #1 void operator()() {} }; static_assert(std::is_constructible_v<C, const C&>);
Here, to determine whether a C can be constructed from a const C lvalue, the overload resolution will attempt to determine whether the constructor marked #1 is a viable candidate, which involves a determination of whether that lvalue can be implicitly converted to a std::function<void()>, which, with the new constraint, requires a determination whether C is copy-constructible — in other words, whether it can be constructed from a C lvalue.
This is similar to LWG 3420: in both cases we have a class (filesystem::path there, function here) that is convertible from every type that are, inter alia, copy constructible, and this then results in constraint recursion when we ask whether a different type that is constructible from such a class is copy constructible. The C above is reduced from an internal helper type in libstdc++. Given the ubiquity of call wrappers — types that are callable in their own right and therefore may not be able to be ruled out by the Lvalue-Callable constraint, and can also naturally have a constructor that take the wrapped function object as the argument, triggering the recursion scenario — it is not clear that there is a good way to add this constraint without causing undue breakage.[ 2021-01-15; Telecon prioritization ]
Set priority to 3 following reflector and telecon discussions.
[ 2020-11-01; Daniel comments ]
This issue has some overlap with LWG 2774.
In P0288, any_invocable is (correctly) constraining its constructor that takes an F:
template<class F> any_invocable(F&& f);Let VT be decay_t<F>.
Constraints:
— […]
— is_constructible_v<VT, F> is true, and
— […]
std::function doesn't do that. According to N4868, [func.wrap.func.con] p8 has a constraint for Lvalue-Callable, but not for copy-constructibility. There is a precondition in p9, but that's not enough for portable well/ill-formedness.
Since this is a constructor, and we want to give the right answer to is_constructible/constructible_from queries, we should add the relevant constraint.History | |||
---|---|---|---|
Date | User | Action | Args |
2021-08-20 17:27:29 | admin | set | messages: + msg12012 |
2021-05-18 01:56:01 | admin | set | messages: + msg11809 |
2021-01-15 21:45:23 | admin | set | messages: + msg11649 |
2020-11-01 16:53:29 | admin | set | messages: + msg11525 |
2020-11-01 16:53:29 | admin | set | messages: + msg11524 |
2020-10-31 00:00:00 | admin | create |