我偶然发现了一个错误,该错误仅在 GCC 6.2.0 上出现,但在 Clang 3.9.0 上没有出现(均在 -std=c++14
模式下)。我不确定哪种行为是正确的(以及我是否应该提交错误)。
代码如下:
template<typename type_t>
class foo_t
{
};
class bar_t
{
public:
using foo_t = int;
};
class baz_t:
public bar_t
{
private:
template<typename type_t>
friend class foo_t;
};
在 GCC 上,这会产生以下错误:
test.cpp:17:15: error: using typedef-name ‘using foo_t = int’ after ‘class’
friend class foo_t;
^~~~~
test.cpp:9:19: note: ‘using foo_t = int’ has a previous declaration here
using foo_t = int;
^
根据我对 C++ 标准的了解,父级 typedef
(或 using
)不应泄漏到子级的范围内,您需要明确限定名称:例如参见Propagating 'typedef' from based to derived class for 'template' .所以在我看来 GCC 在这里是不正确的,但我不太确定我的 C++ 知识可以自信地说。
感谢您的帮助!
最佳答案
From what I know of C++ standard, parent
typedef
's (orusing
s) should not leak into scope of the child and you need to explicitly qualify the name
这是不正确的。在基类中声明的成员(包括类型别名)在派生类中通常是可见的。您链接到的问题专门处理具有依赖基类的模板,其中应用两阶段名称查找(同样,适用于所有内容,而不仅仅是类型别名)。
除此之外,标准的相关部分是 C++14 (N4140) [dcl.type.elab] 7.1.6.3/2(强调我的):
3.4.4 describes how name lookup proceeds for the identifier in an elaborated-type-specifier. If the identifier resolves to a class-name or enum-name, the elaborated-type-specifier introduces it into the declaration the same way a simple-type-specifier introduces its type-name. If the identifier resolves to a typedef-name or the simple-template-id resolves to an alias template specialization, the elaborated-type-specifier is ill-formed.
(注意:elaborated-type-specifier 是我们正在处理的某些 T
的构造 class T
)。
3.4.4 反过来说,当将详细类型说明符中的标识符解析为名称时,将忽略非类型名称(但通常会找到类型名称)。
GCC 因此实际上是正确的,因为范围 bar_t
中的 typedef-name foo_t
在范围上比全局范围模板名称 foo_t “更近”
。 baz_t
中的非限定名称 foo_t
因此解析为 bar_t::foo_t
,这是一个 typedef-name 因此使详细类型说明符格式错误。
问题在于解析不合格 名称foo_t
。正如您在对该问题的评论中指出的那样,明确说明您指的是哪个 foo_t
应该解决该问题:
tempalte <typename type_t>
friend class ::foo_t;
关于c++ - Friend 类、继承和 typedef——哪种行为是正确的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39875499/