微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 gcc 8.2 但不是 MSVC 19 中编译的模板代码

如何解决在 gcc 8.2 但不是 MSVC 19 中编译的模板代码

此示例脚本在 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>();
    }
};

Live Demo

正如 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 未正确实现该异常的情况。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。