Skip to content

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

Description

@hubert-reinterpretcast

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

Activity

  1. hubert-reinterpretcast commented on Jun 5, 2024

    @hubert-reinterpretcast
    MemberAuthor

    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
  2. changed the title [-][temp.deduct.type] Deduction of non-type template arguments with placeholder types[/-] [+]CWG2900 [temp.deduct.type] Deduction of non-type template arguments with placeholder types[/+] on Jun 14, 2024
  3. jensmaurer commented on Jun 14, 2024

    @jensmaurer
    Member
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions