xmh0511
xmh0511

Reputation: 7369

What is the normative rule in the current draft rules that a template parameter pack which does not participate in deduction is deduced to empty

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

[temp.arg.explicit#note-1]

[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

Answers (1)

dfrib
dfrib

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

Related Questions