Is the following code example in compliance with the C++20 standard or should it be rejected due to an ambiguous deduction?
template<typename...>
struct s {
s(int) requires true {}
s(int) {}
};
static_assert(not noexcept(s{{}})); // clang nope, gcc ok, msvc ok
Live example
The error message from Clang:
<source>:6:28: error: ambiguous deduction for template arguments of 's'
6 | static_assert(not noexcept(s{{}}));
| ^
<source>:3:5: note: candidate function [with $0 = <>]
3 | s(int) requires true {}
| ^
<source>:4:5: note: candidate function [with $0 = <>]
4 | s(int) {}
| ^
As indicated by CWG Issue 2628 that Brian Bi linked in his answer, it appears that there currently is no wording in the C++20 standard that mandates the requires-clause of a constructor to be propagated to the implictly-generated deduction guide. As a workaround, it's possible to provide a user-defined deduction guide instead:
template<typename...>
requires true
s(int) -> s<>;
template<typename...>
s(int) -> s<>;
Note that for this particular code example, the deduction guide s(int) -> s<>; would also work, since a user-defined deduction guide is preferred over an implicitly generated one. It seems the consideration here would be quality of error-reporting opposed to less code bloat.
This is CWG 2628: when the compiler forms the implicit deduction guide from the constructor s::s(int) requires true, that deduction guide should also have requires true, which makes it more constrained than the other deduction guide; but the wording currently doesn't specify that the deduction guide gets the constraint. It seems that GCC already does it, but Clang doesn't do it yet.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With