Skip to content

[temp.arg.general] Template argument grammar disambiguation rule versus template template-arguments #669

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
hubert-reinterpretcast opened this issue Feb 3, 2025 · 4 comments

Comments

@hubert-reinterpretcast
Copy link
Collaborator

hubert-reinterpretcast commented Feb 3, 2025

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

Reference (section label): temp.arg.general

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

Issue description:
https://wg21.link/temp.arg.general#3 says that the type-id interpretation is preferred over any "expression" interpretation of a template-argument. Template template-argument‌s are supposed to be id-expression‌s (https://wg21.link/temp.arg.template#1). Following the introduction of https://wg21.link/p0091r3 (class template argument deduction), most template template-argument‌s are ill-formed type-id‌s. See https://wg21.link/dcl.type.simple#3 and https://wg21.link/dcl.type.class.deduct. Even without P0091R3, the disambiguation rule also affects the usage of the usage of the injected-class-name of a class template as a template template-argument.

Consider:

void g();

template <typename T>
struct A {
  static void f() {
    g<A>((A *)0);
    g<A>((A *)0, 0);  // Clang, GCC, EDG accept; MSVC rejects
  }
};

template <typename T> void g(void *);
template <template <typename> class> void g(void *, int);

void h() { A<int>::f(); }

Suggested resolution:
Template arguments that are in the form a of (possibly dependent) "name" can perhaps be parsed as a new, preferred-by-disambiguation, grammar production for template-argument. The (semantic) forms of template argument can be updated to accept appropriate instances of the new grammar production. Not requiring typename for a name that is used as the template-argument for a type template parameter would be consistent with the class template injected-class-name behaviour of Clang, GCC, EDG, and MSVC.

@jensmaurer
Copy link
Member

What's the outcome for the first call to g?

@hubert-reinterpretcast
Copy link
Collaborator Author

hubert-reinterpretcast commented Feb 4, 2025

What's the outcome for the first call to g?

All compilers accept: https://godbolt.org/z/Wh46scW9M

@t3nsor
Copy link

t3nsor commented Feb 20, 2025

Template arguments that are in the form a of (possibly dependent) "name" can perhaps be parsed as a new, preferred-by-disambiguation, grammar production for template-argument.

P2841R7 has changed the grammar in this area to remove id-expression as one of the forms of template argument.

(There's still the fact that I don't know what it means for a dependent name to match the nested-name-specifier(opt) template-name grammar production if it's not actually known what kind of entity the dependent name refers to.)

@hubert-reinterpretcast
Copy link
Collaborator Author

(There's still the fact that I don't know what it means for a dependent name to match the nested-name-specifier(opt) template-name grammar production if it's not actually known what kind of entity the dependent name refers to.)

It wouldn't match. Instead, it would be taken as a non-type non-template name in the template definition context. That's the difference between using the grammar productions that are associated with finding certain kinds of declared names and not using them. This result does not match the intent expressed in the adopted P1787R6 ("Declarations and where to find them") proposal.

Anyhow, the grammar is still ambiguous. If the argument is known to name an injected-class-name of a template, it is also a type. Similarly, if it is otherwise known to name a template, it is also a type-id with a placeholder for CTAD.

Discussions around D2996R10 ("Reflection for C++26") resulted in a solution built around qualified-reflection-name for the similar problem with the ^^ operator.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants