【发布时间】:2014-05-29 17:41:25
【问题描述】:
C++11 标准中的第 7.3.1.2/3 节(重点是我的):
在命名空间中声明的每个名称first都是该名称空间的成员 命名空间。如果非本地类中的友元声明 first 声明 类或函数友元类或函数是 最里面的封闭命名空间。找不到朋友的名字 不合格查找 (3.4.1) 或合格查找 (3.4.3) 直到 在该命名空间范围内提供了匹配的声明( 在授予友谊的类定义之前或之后)。如果有朋友 函数被调用,它的名字可以通过名字查找找到 考虑来自与 函数参数的类型(3.4.2)。如果在朋友的名字 声明既不是限定的,也不是模板 ID 和声明 是一个函数或一个详细的类型说明符,查找来确定 该实体是否先前已申报,不应考虑任何 最里面的封闭命名空间之外的范围。 [注:其他 朋友声明的形式不能声明新成员 最里面的封闭命名空间,因此遵循通常的查找规则。
示例:
// Assume f and g have not yet been defined. void h(int); template <class T> void f2(T); namespace A { class X { friend void f(X); // A::f(X) is a friend class Y { friend void g(); // A::g is a friend friend void h(int); // A::h is a friend // ::h not considered friend void f2<>(int); // ::f2<>(int) is a friend }; }; // A::f, A::g and A::h are not visible here X x; void g() { f(x); } // definition of A::g void f(X) { /* ... */} // definition of A::f void h(int) { /* ... */ } // definition of A::h // A::f, A::g and A::h are visible here and known to be friends } using A::x; void h() { A::f(x); A::X::f(x); // error: f is not a member of A::X A::X::Y::g(); // error: g is not a member of A::X::Y }
除非我遗漏了什么,否则我不明白上面 first 这两个词的必要性。据我所知,命名空间中的任何实体都不能有多个声明,类中的友元函数也不能有多个声明。
另外,示例中“假设 f 和 g 尚未定义”的注释有什么相关性?这些函数是否在命名空间 A 的定义之前声明并不重要。它们必然属于全局命名空间,与命名空间 A 内声明的函数无关。
编辑:
一个人可以重复声明同一个函数,或者在命名空间中声明和定义一个函数,这一事实并没有使我的观察无效,即在§7.3.1.2/3 不是必需的。
编辑1
我刚刚发现另一个错误。评论::f2<>(int) is a friend 不正确。不仅命名空间A中没有模板函数f2(T)的定义,更重要的是,声明template <class T> void f2(T);必须在inside A,否则函数f2<>(int)将不是它的朋友班级A::X::Y。
【问题讨论】:
-
我在参考/声明点上得到了纠正。我撤回了我的答案。
-
As far as I can see, you can't have more than one declaration of any entity in a namespace您可以拥有任意数量的。namespace N { void foo(); void foo(); void foo(); }完全有效。虽然在这个例子中它也完全不相关,所以这不能回答你的问题。 -
On Edit1:我不知道你的测试是什么得出这个结论,但这个例子在这种情况下是正确的。朋友声明
friend void f2<>(int);使::f2<int>成为内部类型的朋友。见this -
@DavidRodríguez-dribeas 您的示例非常人为,令我惊讶的是它完全有效。例如,这个(coliru.stacked-crooked.com/a/e04d9ccf777564d7)应该可以编译,但它当然不会。现在看一个更“正常”的例子(coliru.stacked-crooked.com/a/5c97c2f36e21fbf3)。如果声明
template <class T> void f2(T);不在命名空间内,则代码不会编译,这正是 §7.3.1.2/3 所要求的。 -
也许在聊天中讨论这个会更容易。您提供的第一个链接失败有两个原因:函数名称中的拼写错误 (
accesss) 以及f<int>的特殊化无法访问该函数(因为它不是朋友) .第二个确实编译,看here
标签: c++ c++11 namespaces language-lawyer friend