我偶然发现了一个错误,该错误仅出现在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
s)不应泄漏到子的范围内,您需要明确限定名称:例如参见{{ 3}}。所以在我看来GCC在这里是不正确的,但我不太确定我的C ++知识可以放心地说。
感谢您的帮助!
答案 0 :(得分:4)
根据我所知的C ++标准,父
typedef
(或using
s)不应该泄漏到孩子的范围内,你需要明确限定名称
这是不正确的。在基类中声明的成员(包括类型别名)通常在派生类中可见。您链接的问题专门处理具有依赖基类的模板,其中两阶段名称查找适用(并且同样适用于所有内容,而不仅仅是类型别名)。
除此之外,标准的相关部分是C ++ 14(N4140)[dcl.type.elab] 7.1.6.3/2(强调我的):
3.4.4描述了如何对 elaborated-type-specifier中的标识符进行名称查找。如果标识符 解析为类名或枚举名称, elaborated-type-specifier 将其引入声明中 同样,简单类型说明符引入了类型名称。 如果标识符解析为 typedef-name 或 simple-template-id 解析为别名模板特化, elaborated-type-specifier 格式不正确。
(注意: elaborated-type-specifier 是我们正在处理的某些class T
的构造T
。
foo_t
中的typedef-name bar_t
是&#34;更近&#34;在范围内,而不是全局范围模板名称foo_t
。因此,foo_t
中的非限定名称baz_t
会解析为bar_t::foo_t
,这是 typedef-name ,因此会使详细类型说明符格式错误。< / p>
问题在于不合格名称foo_t
的解析。正如您在对该问题的评论中注意到的那样,明确说明您的foo_t
应该解决问题:
tempalte <typename type_t>
friend class ::foo_t;
答案 1 :(得分:1)
会员&#39;声明对其子类可见。您的问题的问题是重复声明。请检查以下代码
template<typename type_t>
class foo_t
{
};
class bar_t
{
public:
using foo_t = int;
};
class baz_t :
public bar_t
{
public:
foo_t val; // Here, the foo_t refers to the int
};
int main()
{
baz_t().val; // this works
}
您发布的错误代码test.cpp:9:19: note: ‘using foo_t = int’ has a previous declaration here
已经提到了这个问题。
另一方面,朋友类不能应用于简单数据类型,请检查以下代码:
using foo_t = int;
class bar_t
{
public:
};
class baz_t :
public bar_t
{
public:
template<typename type_t>
friend class foo_t;
//error: using typedef-name ‘using foo_t = int’ after ‘class’
};
如果您确实需要具有重复的声明名称,那么这是解决方法:
template<typename type_t>
class foo_t
{
};
class bar_t
{
public:
using foo_t = int;
};
class baz_t:
public bar_t
{
public:
template<typename type_t>
friend class ::foo_t; // The global scope
foo_t val; // The int
};