Chris Fretz
Chris Fretz

Reputation: 437

MSVC Alias Template Bug?

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

Answers (1)

aschepler
aschepler

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 with template) 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

Related Questions