Reputation: 1547
This example script compiles cleanly in gcc 8.2, but in Visual Studio 2019 it returns error C3200: 'bar<int>': invalid template argument for template parameter 'bar', expected a class template
at the line where the 'new' occurs:
template<typename T, template<typename> class bar>
class foo;
template<typename T>
class bar
{
friend class foo<T, bar>;
};
template<typename T, template<typename> class bar>
class foo
{
};
class baz : bar<int>
{
public:
void mash()
{
auto whoosh = new foo<int, bar>();
}
};
int main(int argc, char **argv)
{
baz A;
A.mash();
return 0;
}
Reading around, I think the problem may be that the second template argument in that line is now a well-defined type rather than a template, but even if that's true I don't know what to do about it. Replacing 'bar
' with 'decltype(bar)
' didn't get me anywhere.
I would welcome any suggestions.
https://godbolt.org/z/rrGdvf763
Upvotes: 3
Views: 117
Reputation: 122133
I admit, I don't know who is right or wrong here (see below). The confusion seems to be from the fact that inside the class template baz
inheriting from bar<int>
the identifier bar
is interpreted as bar<int>
. Strangely bar
itself uses bar
to refer to the template not to bar<T>
. And the compilers do not agree. Anyhow, all compilers you included in the conformance view accept the code if you change it to:
class baz : bar<int>
{
public:
void mash()
{
auto whoosh = new foo<int, ::bar>();
}
};
As Jarod42 pointed out:
From injected-class-name#In_class_template: "In the following cases, the injected-class-name is treated as a template-name of the class template itself: - it is used as a template argument that corresponds to a template template parameter". so msvc's bug.
And, thanks to aschepler for the link, the official wording in the standard can be found in [temp.local] in paragraph 1.
So what I called "strange" above is to be expected. For example:
template <typename T>
struct moo {
moo some_method();
//^ refers to moo<T>
foo<int,moo> some_other_method();
// ^ refers to moo
};
And what you encountered is a case where msvc does not correctly implement that exception.
Upvotes: 3