嵌套类中 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<T>::Inner<S>
内这一事实,因此您可以使用 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++ 之间切换