Reputation: 7369
template<typename ...T, typename U>
void fun(U){}
int main(){
fun(0);
}
This snippet code is accepted by both GCC and Clang. The template parameter pack T
does not participate in the template argument deduction in the context of function call, as per the following rules:
[temp.deduct.call]
Template argument deduction is done by comparing each function template parameter type (call it P) that contains template-parameters that participate in template argument deduction with the type of the corresponding argument of the call (call it A) as described below.
The pack T
is contained by any function template parameter. If there were no other special rules specify, the deduction would fail according to:
[temp.deduct.type#2]
if any template argument remains neither deduced nor explicitly specified, template argument deduction fails.
However, such a case is ruled by the following rule in the current standard, that is: [temp.arg.explicit#4]
A trailing template parameter pack ([temp.variadic]) not otherwise deduced will be deduced as an empty sequence of template arguments.
So, the above case can be considered to deduce successfully which leaves the pack T
with an empty set of template arguments.
However, the special rule in temp.arg.explicit#4 has been changed to a note in the current draft
[Note 1: A trailing template parameter pack ([temp.variadic]) not otherwise deduced will be deduced as an empty sequence of template arguments. — end note]
So, I wonder Is there any alternative normative rule in the current draft states that the pack T
not otherwise deduced will be deduced to an empty set of template arguments?
Upvotes: 6
Views: 81
Reputation: 73186
The previously normative section of [temp.arg.explicit]/4
[...] A trailing template parameter pack ([temp.variadic]) not otherwise deduced will be deduced as an empty sequence of template arguments. [...]
was made into a non-normative note as part of P1787R6.
As you've pointed out, as per [temp.deduct.type]/2 [emphasis mine]:
Type deduction is done independently for each
P
/A
pair [...], if any template argument remains neither deduced nor explicitly specified, template argument deduction fails.
[temp.arg.general] describes that a template parameter that is a template parameter pack may correspond to zero template arguments:
[...] When the parameter declared by the template is a template parameter pack, it will correspond to zero or more template-arguments.
and [temp.variadic]/1 explicitly mention that a template parameter pack may accept zero arguments:
A template parameter pack is a template parameter that accepts zero or more template arguments.
followed by a non-normative example of an empty argument list for an entity templated over a parameter pack template parameter:
template<class ... Types> struct Tuple { }; Tuple<> t0; // Types contains no arguments
Now, returning to [temp.arg.explicit]/4:
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.
Meaning the Tuple
example above is can likewise omit the empty argument list
Tuple t0; // Also OK: Types contains no arguments
but where the key is that, as per [temp.arg.general] above, that a template parameter list may correspond to zero arguments, in which case there are no template arguments needed to be deduced.
If you look at your own example:
template<typename ...T, typename U> void fun(U){} int main(){ fun(0); // #1 }
you could likewise invoke #1
as:
fun<>(0); // argument list for parameter pack is empty
// -> no argument (beyond that for `U`) to deduce
highlighting that the deducible argument corresponding to the template parameter U
can be omitted from the explicit template-arguments, whereas the remaining template-arguments are none; namely, the argument list for the template parameter that is a template parameter pack is empty, and there are thus no remaining template arguments that needs to be deduced.
Thus
A trailing template parameter pack ([temp.variadic]) not otherwise deduced will be deduced as an empty sequence of template arguments.
is non-normative/redundant, explaining why it was wrapped into a [Note - [...] - end note].
Upvotes: 0