内联友元函数的范围是什么?
在搜索了一圈之后,一个问题告诉我,内联友元函数的词法范围是它定义的类,这意味着它可以访问类中的 typedef没有资格他们。但后来我想知道这样一个函数的实际范围是什么?GCC 至少拒绝了我调用它的所有尝试。是否可以通过 ADL 以外的方式调用示例中的函数(由于没有参数,这在此处是不可能的)?
标准报价非常感谢,因为我目前无法访问它的副本。
namespace foo{
struct bar{
friend void baz(){}
void call_friend();
};
}
int main(){
foo::baz(); // can't access through enclosing scope of the class
foo::bar::baz(); // can't access through class scope
}
namespace foo{
void bar::call_friend(){
baz(); // can't access through member function
}
}
会导致这些错误:
prog.cpp: In function ‘int main()’:
prog.cpp:9: error: ‘baz’ is not a member of ‘foo’
prog.cpp:10: error: ‘baz’ is not a member of ‘foo::bar’
prog.cpp: In member function ‘void foo::bar::call_friend()’:
prog.cpp:15: error: ‘baz’ was not declared in this scope
After searching aroung SO, one question taught me that the lexical scope of an inline friend function is the class it's defined in, meaning it can access e.g. the typedef
s in the class without qualifying them. But then I wondered what is the actual scope of such a function? GCC at least rejects all my attempts to call it. Can a function such as in the example ever be called through means other than ADL, which is not possible here thanks to no arguments?
Standard quotations are appreciated, as I currently can't access my copy of it.
namespace foo{
struct bar{
friend void baz(){}
void call_friend();
};
}
int main(){
foo::baz(); // can't access through enclosing scope of the class
foo::bar::baz(); // can't access through class scope
}
namespace foo{
void bar::call_friend(){
baz(); // can't access through member function
}
}
results in these errors:
prog.cpp: In function ‘int main()’:
prog.cpp:9: error: ‘baz’ is not a member of ‘foo’
prog.cpp:10: error: ‘baz’ is not a member of ‘foo::bar’
prog.cpp: In member function ‘void foo::bar::call_friend()’:
prog.cpp:15: error: ‘baz’ was not declared in this scope
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
当您在类中声明具有非限定 id 的
friend
函数时,它会在最近的封闭命名空间范围中命名一个函数。如果该函数之前尚未声明,则
friend
声明不会使该函数在正常查找的范围内可见。它确实使声明的函数对参数相关的查找可见。许多注释都强调了这一点,但最终声明在 7.3.1.2/3(ISO/IEC 14882:2011)中:
When you declare a
friend
function with an unqualified id in a class it names a function in the nearest enclosing namespace scope.If that function hasn't previously been declared then the
friend
declaration doesn't make that function visible in that scope for normal lookup. It does make the declared function visible to argument-dependent lookup.This is emphasised in many notes, but the definitive statement is in 7.3.1.2/3 (of ISO/IEC 14882:2011):
“C++ 编程语言第 3 版(Stroustrap)”:p279:
I.“与成员声明一样,友元声明不会将名称引入封闭范围”
II。 “友元类必须事先在封闭范围中声明或在非类中定义
范围立即包含将其声明为友元的类”
III.“友元函数可以像友元类一样显式声明,也可以通过其参数类型(第 8.2.6 节)找到它,就像在非类中声明一样
作用域立即包含其类。”
IV. “因此,友元函数应该在封闭作用域中显式声明,或者采用其类的参数。如果没有,则无法呼叫该朋友。例如:“
但在你的情况下,还有更多与命名空间有关的事情,因为如果你在 foo 中放入正确的声明,eg:
不会编译。但是,如果你在 foo 之外声明它,它就像一个魅力。现在考虑一下,事实上,全局、局部、结构和类实际上都是命名空间。现在这导致了这样的结论:baz(const &) 是在全局范围内隐式定义的
。 :
因此,有两个问题
谢谢,希望它有所帮助,但当然,我喜欢这个挑战:)。
"The C++ Programming Language 3rd Edition (Stroustrap)" : p279:
I. "Like a member declaration, a friend declaration does not introduce a name into an enclosing scope"
II. "A friend class must be previously declared in an enclosing scope or defined in the nonclass
scope immediately enclosing the class that is declaring it a friend"
III. "A friend function can be explicitly declared just like friend classes, or it can be found through its argument types (§8.2.6) as if it was declared in the nonclass
scope immediately enclosing its class."
IV. "It follows that a friend function should either be explicitly declared in an enclosing scope or take an argument of its class. If not, the friend cannot be called. For example:"
But in your case there is more to it that has to do with the namespace, because if you put the proper declaration in foo e.g.:
does not compile. However, if you declare it outside foo is works like a charm. Now consider that in fact, global, local, struct, and classes are in fact namespaces. Now this leads to the conclusion that the
baz(const &)
is implicitly defined in the global scope.This compiles:
Therefore, there are two issues:
Thanks, hope it helps, but certainly, I liked the challenge :) .
有趣的!
编译器似乎不知道它属于哪个作用域(老实说没有线索),因此没有放入任何作用域。我想一些标准的挖掘即将到来。
注意:如果您显式地将声明添加到特定范围,那么它就会开始按预期工作。
挖掘我发现的标准:
11.3 Friends [class.friend]
第 6 段
第 7 段
注意:
不带参数的独立函数对于朋友来说没有多大用处。因为它没有可以利用其友谊的对象(我认为文件范围静态存储持续时间对象)。
Interesting!
It seems that the compiler does not know what scope it belongs to (and to be honest there are no clues) and thus puts in in no scope. Some standard digging coming up I suppose.
Note: If you explicitly add a declaration to a particular scope then it starts to work as expected.
Digging the standard I find:
11.3 Friends [class.friend]
Paragraph 6
Paragraph 7
Note:
A free standing function that does not take a parameter is not much use as a friend. As it will have no object on which to take advantage of its friendship (I suppose file scope static storage duration objects).
在封闭类中
定义的
friend
函数只能通过参数依赖查找(ADL)找到。当一个或多个参数是封闭类类型之一时,调用它将成功;或类内声明的类型。下面是一个显示“Hello World!”的示例,它(出于多样性)不使用封闭类类型的对象来提供这样的参数:A
friend
function defined within an enclosing class, will only be found by argument dependent lookup (ADL). Calling it will succeed when one or more of the arguments is either of the enclosing class type; or of a type declared within the class. Here is an example, displaying "Hello World!", which (for variety) doesn't use an object of the enclosing class type to provide such an argument:在此示例中,
foo::baz()
不可访问,因为名称baz
在命名空间foo
范围内不可见。如果我没记错的话(§ 3.4/2)适用于此。foo::bar::baz()
无法访问,因为友元不是类的成员,并且内联友元函数的范围是其定义所在的命名空间或类,因此,您可以'不能在该范围之外访问它们。如果将
baz()
声明放入foo
中,则函数baz
的名称将在foo
中可见,并且该定义将在bar
的嵌套范围中查找。In this Example,
foo::baz()
is inaccessible because the namebaz
is not visible in scope of namespacefoo
. If I remember correctly (§ 3.4/2) applies here.foo::bar::baz()
is inaccessible because friends aren't members of class and the scope of inline friend function is namespace or class in which their definition exists therefore, you can't access them outside of that scope.If you put the declaration of
baz()
infoo
the name of functionbaz
will be visible infoo
and the definition will be looked up in the nested scope ofbar
.我遇到了类似的问题...
下面的代码的非直观非功能确实让我感到惊讶,尽管它可能在标准范围内:-(
I ran into a similar problem...
The non-intuitive non-functioning of the code below really surprised me, although it's probably within the standard :-(
我认为您混淆了
friend
和private
。通过将函数声明为friend
,您将授予它对您的私有成员的访问权限,并且不会授予其他函数对其的访问权限。无论如何,任何对象都可以访问 struct 的任何成员函数,因为 struct 成员默认是公共的。但是,在您的情况下
baz
无法访问,因为通过执行friend void baz(){}
您并没有真正声明函数baz
,你刚才说它是一个friend
函数。您只需删除friend
关键字即可解决所有问题。I think you are confusing
friend
andprivate
. By declaring function afriend
you are granting it access to your private members, and not grating other functions access to it. Anyway, any member function of astruct
is accessible by any object becausestruct
members are public by default.However, in your case
baz
isn't accessible because by doingfriend void baz(){}
you didn't really declare the functionbaz
, you just said that it is afriend
function. You can just remove thefriend
keyword, and it will solve all the issues.