Reputation: 437
I'm in the midst of converting a library I had previously written for clang and gcc onto MSVC, and I ran into what I assume has to be a bug, but I'm not versed enough with the standard to say for sure.
The following code produces errors about undeclared identifiers and invalid default arguments:
template <class T>
struct dummy_struct {};
template <class T>
using dummy_alias = dummy_struct<T>;
template <template <class> class Thing>
struct foo {
template <template <class> class T = Thing>
void bar() {}
};
int main() {
foo<dummy_alias> fdsa;
fdsa.bar();
}
error C3202: 'Thing': invalid default argument, expected a class template
note: see reference to class template instantiation 'foo<dummy_alias>' being compiled
error C2065: 'Thing': undeclared identifier
Here's a Compiler Explorer link for the above example: https://godbolt.org/z/e2SEpD
The root of the issue appears to be MSVC being uncomfortable with alias templates being used as template template parameters.
I assume this has to be a bug, but I figured I'd run it by those potentially more familiar with the standard before I submit a report. Thanks in advance!
To clarify, this code compiles without issue on recent versions of gcc, clang, and icc.
Upvotes: 3
Views: 235
Reputation: 72271
By a strict reading of the Standard, the program is ill-formed, so gcc and clang are wrong not to print a diagnostic.
However, I suspect the intent was that this should work, so maybe a Standard Defect Report is in order.
[temp.param]/3 says
A type-parameter whose identifier does not follow an ellipsis defines its identifier to be a typedef-name (if declared without
template
) or template-name (if declared withtemplate
) in the scope of the template declaration.
So a template template parameter like Thing
is a template-name, which makes it valid to write a simple-template-id like Thing<int>
.
But [temp.arg.template]/1 says
A template-argument for a template template-parameter shall be the name of a class template or an alias template, expressed as id-expression.
(Technically a default template argument is not syntactically a template-argument, since the template-parameter syntax tree doesn't use the non-terminal template-argument after the =
token, instead using type-id and id-expression directly. However, [temp.param]/11 makes them related, since the type-id or id-expression could be parsed as a template-argument: "A default template-argument is a template-argument ([temp.arg]) specified after =
in a template-parameter.")
Here Thing
is certainly not the name of a class template, and nothing says it's the name of an alias template, just a template-name.
Upvotes: 1