为什么 gcc 无法从其前向声明中检测到 friend class 名称空间?
Why gcc cannot detect friend class namespace from its forward declaration?
我有以下代码可以用 VS2015 编译,但不能用 gcc(任何版本)编译。对我来说,class A_Creator
的命名空间已正确定义(即根命名空间),因为它已在程序顶部进行了前向声明。为什么 gcc 无法正确检测到 A_Creator
class 的命名空间?哪个编译器是正确的?
#include <list>
class A_Creator;
namespace X
{
class A
{
private:
int mX;
A(int x) :
mX(x)
{}
// GCC complains about this line, and it should be changed to ::A_Creator
// On VS2015, both of them are working
friend class A_Creator;
};
} // namespace X
class A_Creator
{
public:
std::list<X::A> TestOnList(int z)
{
std::list<X::A> a_list;
a_list.push_back(X::A(z));
return a_list;
}
};
int main()
{
A_Creator a_cr;
auto x = a_cr.TestOnList(12);
}
If the name in a friend
declaration is neither qualified nor a template-id and the declaration is a function or an elaborated-type-specifier, the lookup to determine whether the entity has been previously declared shall not consider any scopes outside the innermost enclosing namespace. [Note: The other forms of friend declarations cannot declare a new member of the innermost enclosing namespace and thus follow the usual lookup rules. — end note]
由于您在 friend
声明 (friend class A_Creator;
) 中详细说明了类型说明符,因此只能在最里面的封闭命名空间 ::X
中搜索以前的声明。所以,gcc是对的。
[namespace.memdef]/3 中示例的相关摘录,其中包含函数的全局前向声明而不是 class:
void h(int);
namespace A {
class X {
class Y {
friend void h(int); // A::h is a friend
// ::h not considered
};
};
}
我有以下代码可以用 VS2015 编译,但不能用 gcc(任何版本)编译。对我来说,class A_Creator
的命名空间已正确定义(即根命名空间),因为它已在程序顶部进行了前向声明。为什么 gcc 无法正确检测到 A_Creator
class 的命名空间?哪个编译器是正确的?
#include <list>
class A_Creator;
namespace X
{
class A
{
private:
int mX;
A(int x) :
mX(x)
{}
// GCC complains about this line, and it should be changed to ::A_Creator
// On VS2015, both of them are working
friend class A_Creator;
};
} // namespace X
class A_Creator
{
public:
std::list<X::A> TestOnList(int z)
{
std::list<X::A> a_list;
a_list.push_back(X::A(z));
return a_list;
}
};
int main()
{
A_Creator a_cr;
auto x = a_cr.TestOnList(12);
}
If the name in a
friend
declaration is neither qualified nor a template-id and the declaration is a function or an elaborated-type-specifier, the lookup to determine whether the entity has been previously declared shall not consider any scopes outside the innermost enclosing namespace. [Note: The other forms of friend declarations cannot declare a new member of the innermost enclosing namespace and thus follow the usual lookup rules. — end note]
由于您在 friend
声明 (friend class A_Creator;
) 中详细说明了类型说明符,因此只能在最里面的封闭命名空间 ::X
中搜索以前的声明。所以,gcc是对的。
[namespace.memdef]/3 中示例的相关摘录,其中包含函数的全局前向声明而不是 class:
void h(int);
namespace A {
class X {
class Y {
friend void h(int); // A::h is a friend
// ::h not considered
};
};
}