cplusplus / CWG

Core Working Group
23 stars 7 forks source link

CWG2900 [temp.deduct.type] Deduction of non-type template arguments with placeholder types #546

Open hubert-reinterpretcast opened 1 month ago

hubert-reinterpretcast commented 1 month ago

Full name of submitter (unless configured in github; will be published with the issue): Hubert Tong

Reference (section label): [temp.deduct.type]

Link to reflector thread (if any): N/A

Issue description: https://wg21.link/temp.deduct.type#20 has

If P has a form that contains <i>, and if the type of i differs from the type of the corresponding template parameter of the template named by the enclosing simple-template-id, deduction fails.

This wording does not address what happens when the declared type of i is a placeholder type: the corresponding template argument can be read as being i (and the placeholder type deduction process would then be circular).

This wording also does not address what happens when the type of the corresponding template parameter of the template named by the enclosing simple-template-id is a placeholder type.

Suggested resolution:

If P has a form that contains <i>, deduction fails unless the type of i is the same as that of the corresponding template parameter p in the specialization (from A) of the template named by the enclosing simple-template-id; if the declared type of i contains a placeholder type, the corresponding template argument for the purposes of placeholder type deduction ([dcl.type.auto.deduct]) is an id-expression for p.

Examples: Template parameter of the template named by the enclosing simple-template-id is auto or decltype(auto):

template<auto> struct A;
template<long long x> void f(A<x> *);
void g(A<0LL> *ap) { f(ap); }  // OK, deduces `long long` value from `0LL`

i is declared withauto:

template<int> struct A;
template<auto x> void f(A<x> *);
void g(A<0LL> *ap) { f(ap); }  // OK, deduces `x` as an `int` value

template<int &> struct B;
template<auto x> void f(B<x> *);
int v;
void g(B<v> *bp) { f(bp); }  // error: type `int` of `x` does not match the `int &` type of the template parameter in the `B<v>` specialization of `B`

i is declared with decltype(auto):

template<const int &> struct A;
template<decltype(auto) x> void f(A<x> *);
int i;
void g(A<i> *ap) { f(ap); }  // OK, deduces `x` as a `const int &` non-type template parameter
hubert-reinterpretcast commented 4 weeks ago

I believe this also means that all i declared with decltype(auto) in P can be deduced from the corresponding non-type template argument for the specialization from A.

template <decltype(auto)> struct A;
template <auto x> long *f(A<x> *);  // #1
template <decltype(auto) x> short *f(A<x> *);  // #2

const int i = 0;
short *g(A<(i)> *ap) { return f(ap); }  // OK, only #2 matches
long *g(A<i> *ap) { return f(ap); }  // OK, #1 is more specialized
jensmaurer commented 2 weeks ago

CWG2900