C++ 做c++;内联友元函数导致名称隐藏在名称空间之间?
考虑以下代码:C++ 做c++;内联友元函数导致名称隐藏在名称空间之间?,c++,C++,考虑以下代码: namespace Foo1 { void add( int ) {} void subtract( int ) {} } namespace Foo2 { class Bar { public: friend void add( Bar ) {} }; void subtract( Bar ) {} void xxx() { int i = 0; using namespace F
namespace Foo1 {
void add( int ) {}
void subtract( int ) {}
}
namespace Foo2 {
class Bar {
public:
friend void add( Bar ) {}
};
void subtract( Bar ) {}
void xxx() {
int i = 0;
using namespace Foo1;
add( i ); // Is this an error or not?
subtract( i ); // This is an error due to name hiding
}
}
在Foo2::xxx()
中,我使用使用名称空间来访问Foo1::add
和Foo1::subtract
。调用subtract显然是一个错误,因为Foo2::subtract
隐藏名称。但是Foo2::add
不应该在Foo2
中真正可见,因为它只能
可以使用ADL找到,它不应该隐藏Foo1::add
。我的理解正确吗
我已经在MSVC和gcc的多个版本上尝试了上述代码。前者一直是如此
拒绝了添加(i)呼叫,但我不清楚错误消息。后者一直接受这一点。以下哪项(如果有的话)是正确的?我认为GCC就在这里 [namespace.memdef](强调我的) 如果非本地类中的友元声明首先声明 类、函数、类模板或函数模板朋友是 最内层封闭命名空间的成员朋友宣言 本身不会使名称对非限定查找可见 ([basic.lookup.unqual])或限定查找([basic.lookup.qual])。 [ 注意:如果 在命名空间范围中提供了匹配声明(在之前或之后) 课程结束后(给予友谊)。 — 尾注 ] 如果 调用友元函数或函数模板时,可以找到其名称 按名称查找,该查找考虑来自名称空间和 和函数参数类型关联的类 ([basic.lookup.argdep])
这样,不合格的<代码>添加(i)< /> >本身不应该找到<代码>添加(bar)< /代码>的声明,这意味着查找应该继续,并考虑使用指令所带来的名称。并且由于该参数不是类类型,所以ADL是不可能的。<代码>不应隐藏<代码>添加(int)< /> > .< /p> ,如已经指出的(C++ 20标准,7.7.1.2命名空间成员定义)
3如果非本地类中的友元声明首先声明一个类, 函数、类模板或函数模板100朋友是 最内层封闭命名空间的成员 因此,此友元函数add
是名称空间Foo2的成员。但是,在名称空间Foo2
中出现相应的函数声明之前,它在名称空间Foo2
中是不可见的。只有通过依赖于参数的查找才能找到它
namespace Foo2 {
class Bar {
public:
friend void add( Bar ) {}
};
//..
如果在函数xxx
之前写入,则命名空间Foo1
中的名称add
将被隐藏
namespace Foo2 {
class Bar {
public:
friend void add( Bar ) {}
};
void add( Bar );
//...
void xxx() {
int i = 0;
using namespace Foo1;
add( i ); // Is this an error or not?
subtract( i ); // This is an error due to name hiding
}
也就是说,如果友元函数add
将在封闭的命名空间中重新声明
在函数内xxx
namespace Foo2 {
class Bar {
public:
friend void add( Bar ) {}
};
void add( Bar );
//...
void xxx() {
int i = 0;
using namespace Foo1;
add( i ); // Is this an error or not?
subtract( i ); // This is an error due to name hiding
}
编译器按以下顺序考虑名称substract。首先它查看封闭的名称空间,即名称空间Foo2
。此名称空间具有声明的名称substract
。因此搜索过程停止。重载函数void substract(int)未找到
,因为由于using指令,它被视为全局命名空间的成员。全局命名空间是包含using指令中指定的命名空间的命名空间和包含using指令的命名空间的命名空间
您可以考虑以下方式(由于使用DouTibe)
您可以使用using声明代替using指令,使命名空间Foo1中的两个函数在函数xxx中可见 比如说void xxx() {
int i = 0;
using Foo1::subtract, Foo1::add;
add( i ); // Is this an error or not?
subtract( i ); // This is an error due to name hiding
}
@彼得-朋友不是班上的成员,而是朋友them@Peterfriend函数实际上不属于该类,即使它们是在类主体中定义的。@Peter A friend不是其类的成员。肯定没有
Foo2::Bar::add
。add
定义了Foo2
的成员,但是不会自动声明为可见的Foo2
声明,因此只能通过依赖参数的查找找到它。subtract(i)
是一个错误,因为名称隐藏。请查看@j_kubik Oh我没有注意。我更新了我的答案。