Description
The two examples (with a7
and a8
) from [over.match.class.deduct]-p6 (draft of Nov 2024):
template <class T> struct A {
explicit A(const T&, ...) noexcept; // #1
A(T&&, ...); // #2
};
...
template <class T> A(const T&, const T&) -> A<T&>; // #3
template <class T> explicit A(T&&, T&&) -> A<T>; // #4
...
A a7 = {0, i}; // error: #3 deduces to A<int&>, #1 and #2 declare same constructor
A a8{0,i}; // error: #3 deduces to A<int&>, #1 and #2 declare same constructor
are wrong, as preliminary discussed on:
https://lists.isocpp.org/std-discussion/2024/11/2715.php (and 2718.php)
https://lists.isocpp.org/std-discussion/2024/11/2736.php
Indeed, deduction fails because guides from #2
and #3
(see the full example in standard text or on godbolt link) are non matching better each other (see https://godbolt.org/z/oejf5P1Tc).
The aforementioned text reads, instead, that #3
wins (successful deduction) and then the error is because, consequently, constructors #1
and #2
ambiguate, which would be true in case the deduction had led to T = int&
.
I would propose the following changes, one with the error about overload resolution between two deduction guides, and one where a deduction guide wins and two equivalent constructors are consequently generated, so that both topics of the original comments are shown. I guess it is not that important to select between copy-list-initialization (a7
) or not (a8
), as another example (see a5
in standard text) already shows that the explicit
user-defined deduction guide is involved (as per the text of [over.match.list]).
A a7 = {0, i}; // error: #2 and #3 both match, overload resolution fails
A a8{i,i}; // error: #3 deduces to A<int&>, #1 and #2 declare same constructor
(see https://godbolt.org/z/9Ecf8943x)
Do you believe it is interesting to highlight that even #1
matches for a7
? (but #3
wins compared to it).
See PR #7444