问题描述
此示例脚本在 gcc 8.2 中完全编译,但在 Visual Studio 2019 中,它在出现“new”的行返回 error C3200: 'bar<int>': invalid template argument for template parameter 'bar',expected a class template
:
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;
}
仔细阅读,我认为问题可能是该行中的第二个模板参数现在是定义良好的类型而不是模板,但即使是这样,我也不知道是什么做这件事。用 'bar
' 替换 'decltype(bar)
' 并没有帮助我。
我欢迎任何建议。
https://godbolt.org/z/rrGdvf763
解决方法
我承认,我不知道这里谁对谁错(见下文)。混淆似乎来自这样一个事实,即在继承自 baz
的类模板 bar<int>
中,标识符 bar
被解释为 bar<int>
。奇怪的是 bar
本身使用 bar
来指代模板而不是 bar<T>
。编译器不同意。无论如何,如果您将代码更改为:
class baz : bar<int>
{
public:
void mash()
{
auto whoosh = new foo<int,::bar>();
}
};
正如 Jarod42 指出的:
来自injected-class-name#In_class_template:“在以下情况下,注入的类名被视为类模板本身的模板名: - 它用作对应于模板模板参数的模板参数”。所以是msvc的bug。
而且,感谢 aschepler 提供的链接,标准中的官方措辞可以在第 1 段的 [temp.local] 中找到。
所以我上面所说的“奇怪”是可以预料的。例如:
template <typename T>
struct moo {
moo some_method();
//^ refers to moo<T>
foo<int,moo> some_other_method();
// ^ refers to moo
};
您遇到的是 msvc 未正确实现该异常的情况。