c++ - Friend 类、继承和 typedef——哪种行为是正确的?

标签 c++ gcc clang

我偶然发现了一个错误,该错误仅在 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 (or usings) 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/

相关文章:

c++ - 什么是 clang++ 选项以便在 GDB 中我可以使用 std::cout 作为函数参数

c++ - 由于 emmintrin.h,即使使用 -msse2 标志,Clang-cl 也无法构建 NSS lib

c++ - 模板重新声明中的模板参数过多

c++ - 在多线程代码中转发

c++ - 三元运算中的位域作为左值

c++ - 邻接表函数中的段错误

C++ ifstream 类型错误

c++ - gcc/diab : keep unused function/sections

c++ - 正则表达式 字母数字和符号 [-*/]

c - 有关 C 函数原型(prototype)和编译的问题