This is gcc bug 80871. What follows is an explanation of why the code is well-formed (and clang is correct in deciding that t2
is a custom_tuple<int>
).
The process for figuring out what to do with
custom_tuple t2(42);
basically involves synthesizing a bunch of functions and performing overload resolution on them. The relevant candidates are the synthesized functions from the one constructor and the deduction guide:
template <class... T, class... Args>
custom_tuple<T...> foo(Args... ); // the constructor
template <class... Args>
custom_tuple<Args...> foo(Args... ); // the deduction guide
From this point it's a choose your own adventure based on your interpretation of what a "trailing parameter pack" is according to [temp.arg.explicit]/3:
A trailing template parameter pack not otherwise deduced will be deduced to an empty sequence of template arguments. If all of the template arguments can be deduced, they may all be omitted; in this case, the empty template argument list <>
itself may also be omitted.
T...
isn't trailing
This case is easy. We only have one viable candidate (because T...
isn't deducible) - the deduction-guide candidate. We deduce Args...
as {int}
, so we end up with custom_tuple<int>
.
T...
is trailing
Both gcc and clang actually do consider deduction to succeed for the constructor. So we go to the tiebreakers in [over.match.best]:
Given these definitions, a viable function F1
is defined to be a better function than another viable function F2
if [...]
F1
and F2
are function template specializations, and the function template for F1
is more specialized than the template for F2
according to the partial ordering rules described in [temp.func.order], or, if not that,
F1
is generated from a deduction-guide ([over.match.class.deduct]) and F2
is not, or, if not that, [...]
For purposes of partial ordering, the relevant types are just those which correspond to function parameters, and we're allowed to ignore unused template parameters, so neither function template is considered more specialized than the other.
This leaves us to simply preferring the deduction-guide, which has been the simplest step of this whole process. We deduce Args...
as {int}
, so we end up with custom_tuple<int>
.
Either way, custom_tuple<int>
is the correct decision.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…