Date: Wed, 20 Nov 2024 23:50:24 +0100
The following example is likely wrongly discussed in standard text of
[over.match.class.deduct]
Such examples are also managed by the major compilers (gcc, mvsc, clang)
differently from the standard comments.
p6, Example 2:
template <class T> struct A { explicit A(const T&, ...) noexcept; // #1 A(T&
&, ...); // #2 }; int i; ... 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
The example reads that the selected guide is from the (user-defined)
deduction guide #3.
However, ok for #4 not matching, as there T is ambiguously deduced as int
from first function parameter and int& from second one.
Ok that #3 is better than #1 as the notional constructor related to #1 has
ellipsis, with lowest priority in overload resolution.
But, #2 is not worse than #3. Indeed, for #2 T is deduced as int and
A(int&&, ...) is the winner for the first argument.
Since #3 is the winner for second argument, here we have ambiguity.
Ambiguity is confirmed also by clang (that correctly lists #2 and #3 as
candidates), by mvsc (it lists also #4, a bit weird, but never mind), and
by gcc that just reads about argument deduction failed.
In conclusion, I guess that "#3 deduces to A<int&> is misleading.
Additionally, the statement "#1 and #2 declare same constructor" is also
misleading: they both matching the list-initialization with {0,i} and
deducing int, but they do not lead to the same constructor (const in& is
not int &&).
I hope you may also consider the following doubt that I was studying when I
found the problem above:
[over.match.class.deduct]
Such examples are also managed by the major compilers (gcc, mvsc, clang)
differently from the standard comments.
p6, Example 2:
template <class T> struct A { explicit A(const T&, ...) noexcept; // #1 A(T&
&, ...); // #2 }; int i; ... 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
The example reads that the selected guide is from the (user-defined)
deduction guide #3.
However, ok for #4 not matching, as there T is ambiguously deduced as int
from first function parameter and int& from second one.
Ok that #3 is better than #1 as the notional constructor related to #1 has
ellipsis, with lowest priority in overload resolution.
But, #2 is not worse than #3. Indeed, for #2 T is deduced as int and
A(int&&, ...) is the winner for the first argument.
Since #3 is the winner for second argument, here we have ambiguity.
Ambiguity is confirmed also by clang (that correctly lists #2 and #3 as
candidates), by mvsc (it lists also #4, a bit weird, but never mind), and
by gcc that just reads about argument deduction failed.
In conclusion, I guess that "#3 deduces to A<int&> is misleading.
Additionally, the statement "#1 and #2 declare same constructor" is also
misleading: they both matching the list-initialization with {0,i} and
deducing int, but they do not lead to the same constructor (const in& is
not int &&).
I hope you may also consider the following doubt that I was studying when I
found the problem above:
Received on 2024-11-20 22:50:36