嵌套类中 g++ 和 clang++ 之间的不同行为

Posted

技术标签:

【中文标题】嵌套类中 g++ 和 clang++ 之间的不同行为【英文标题】:Different behavior between g++ and clang++ in nested classes 【发布时间】:2020-02-09 17:04:19 【问题描述】:

我注意到gcc 9.2.0 和clang++ 9.0.1 之间的行为不同。我的代码如下

//header.hh
     ...
template <typename T>
class Outer 
     ...
  public:
     template <typename S>
     class Inner;
     ... 
;

template <typename T>
template <typename S>
class Inner 
     ...
      Inner& func();
     ...
;

那么,由于函数func()是在另一个文件中实现的

//implementation.cc
template <typename T>
template <typename S>
Outer<T>::Inner<S>& Outer<T>::Inner<S>::func() 
    ...
;

现在,如果我使用g++,编译就可以了。如果我使用clang++ 我会得到

src/implementation.cc:6:1: error: missing 'typename' prior to dependent type template name 'Outer<T>::Inner'
Outer<T>::Inner<S>& Outer<T>::Inner<S>::func() 
^
1 error generated.

但是,如果我按照它的建议使用

typename Outer<T>::Inner<S>& Outer<T>::Inner<S>::func()

我又遇到了一个错误:

src/implementation.cc:6:21: error: use 'template' keyword to treat 'Inner' as
a dependent template name typename Outer<T>::Inner<S>& Outer<T>
::Inner<S>::func() 

现在它的建议似乎很奇怪。

问题

    为什么两个编译器的行为不同? 使用的正确语法是什么?

【问题讨论】:

你有一个更大的问题要担心。即使在您解决编译错误之后,尽管您的问题提供的信息有限,但您的程序似乎很可能无法通过任一编译器链接,因为模板只能在头文件中实现。您在名为“implementation.cc”的东西中定义模板的尝试注定要彻底失败。 C++ 根本无法以这种方式工作。 能否请您更新您的示例,它们与错误消息不一致(例如 Inner-Outer order、Iterator 类)。 同样,你需要edit你的问题只包含一个代码sn-p来演示你所询问的编译错误。 我编辑了这个问题。不过我很抱歉我的无知。我只是不知道不能将模板的定义与声明分开。 您的问题仍然缺少minimal reproducible example。您可以剪切/粘贴您的问题中的内容,并重现您的编译错误吗?显然不是,直到它是,它不是定义上的minimal reproducible example。获得此类帮助的最佳方式是让其他人尽可能轻松地重现您的错误。 【参考方案1】:

正确的语法如下:

template <typename T>
template <typename S>
typename Outer<T>::template Inner<S> &Outer<T>::Inner<S>::func() 
    ...

您可以在this 问题中找到此语法的完整说明。

但是,更简单且有效的语法是这样的:

template <typename T>
template <typename S>
auto Outer<T>::Inner<S>::func() -> Inner& 
    ...

通过在上例中使用尾随返回类型语法,您可以利用名称解析范围在 Outer&lt;T&gt;::Inner&lt;S&gt; 内这一事实,因此您可以使用 Inner 的 injected class name。

【讨论】:

以上是关于嵌套类中 g++ 和 clang++ 之间的不同行为的主要内容,如果未能解决你的问题,请参考以下文章

g++5 中 std::unordered_set 编译错误的不完整类型,在 clang++ 中编译

如何在数据框同一列的不同行之间执行集合之间的联合

如何在 Access 2016 中的另一列上选择具有最大值的不同行

两级嵌套 c++ 类适用于 GCC,但使用 Clang 失败

g++ 和 clang++ 使用变量模板和 SFINAE 的不同行为

如何在 Qt creator 中更改/配置所需的编译器?即在 MSVC/Mingw 或 g++/clang++ 之间切换