这个片段编译成clang,
namespace A {
void f() {
void g();
g();
}
}
void A::g() { }
Run Code Online (Sandbox Code Playgroud)
但GCC只接受代码,如果g在命名空间内定义A如下:
namespace A {
void f() {
void g();
g();
}
void g() {}
}
Run Code Online (Sandbox Code Playgroud)
但我相信[basic.link]/7中没有任何内容禁止上面的第一个片段.
[basic.link]/6
在块作用域中声明的函数的名称和由块作用域
extern声明声明的变量的名称具有链接.如果存在具有相同名称和类型的链接的实体的可见声明,忽略在最内部封闭命名空间范围之外声明的实体,则块范围声明声明该实体并接收先前声明的链接.如果存在多个这样的匹配实体,则该程序是不正确的.否则,如果未找到匹配的实体,则块范围实体将接收外部链接.[示例:Run Code Online (Sandbox Code Playgroud)static void f(); static int i = 0; // #1 void g() { extern void f(); // internal linkage int i; // #2 i has no linkage { extern void f(); // internal linkage extern int i; // #3 external linkage } }
i此程序中有三个对象.具有内部链接的对象由全局范围内的声明引入(第1行),具有自动存储持续时间的对象并且没有由第2行上的声明引入的链接,以及具有静态存储持续时间和由声明引入的外部链接的对象在第3行. - 末端的例子]
我对这一段有两点评论:
static int i = 0;全局范围内的声明在包含声明的块(#3)中不可见extern int i;.因此,我们只能说后一种宣言具有外部联系,即我们不能将其与宣言#1联系起来.static int i;被声明#3视为可见,则根据段落中的文本,块作用域声明声明相同的实体并接收前一声明的链接,即内部链接,而不是外部链接,如实施例中所述.我在这里错过了什么?
GCC,clang和VS2013编译下面的代码:
namespace A{}
int main()
{
int A;
}
Run Code Online (Sandbox Code Playgroud)
但[namespace.alias]/4表示如下:
一个命名空间名称或命名空间别名不得申报为同一任何其他实体的名称声明区.
和
[basic.scope.declarative]/1说:
每个名称都在程序文本的某些部分中引入,称为 声明性区域,该声明区域是该名称有效的程序的最大部分,也就是说,该名称可以用作非限定名称以引用同一实体.
也就是说,我的印象是int变量in main()不能与命名空间同名A.注意到[basic.scope.declarative]/2中的例子似乎证实了这一点
第一个j 的声明区域包括整个示例.
struct A{};
int A;
struct A a;
struct A::A b;
Run Code Online (Sandbox Code Playgroud)
上面的最后两个声明是等价的.它们都声明了类型A的对象.在标准中我可以找到或推断出这个吗?
§8/ 5:
可选属性说明符-SEQ的尾返回型 appertains所指示的返回类型.的类型ID的 尾返回型包括的可能的最长序列抽象声明符秒.[注意:这解决了数组和函数声明符的模糊绑定.[例如:
Run Code Online (Sandbox Code Playgroud)auto f()->int(*)[4]; // function returning a pointer to array[4] of int // not function returning array[4] of pointer to int- 末端示例] - 尾注]
" trailing-return-type中的type-id "对我来说没有意义,只是因为trailing-return-type根据语法不包含type-id.
我也不理解数组和函数声明的"模糊绑定".据我所知
auto f() -> int*[4]; // function returning an array of 4 pointers to int
auto f() -> int(*)[4]; // function returning a pointer to an array of 4 ints
Run Code Online (Sandbox Code Playgroud) 在[basic.lookup.classref]/7(C++ 14)中我们有(重点是我的):
如果id-expression是conversion-function-id,则首先在对象表达式的类中查找其 conversion-type-id,并使用名称(如果找到).否则,它将在整个postfix-expression的上下文中查找.在每个查找中,仅考虑表示其特化类型的类型或模板的名称.
我不明白上面的其他需要.因此,我想看一个示例,其中在整个postfix-expression的上下文中查找conversion-type-id.
[basic.def.odr]/2中的示例以下面的句子开头:
在下面的示例中,n的初始值设定项的潜在结果集包含第一个S :: x子表达式,但不包含第二个S :: x子表达式.
从本段的定义中,我们如何推断出n的初始值包含第一个S :: x子表达式,而不是第二个S :: x子表达式?
编辑 请参阅下面上面提到的示例的其余部分:
struct S { static const int x = 0; };
const int &f(const int &r);
int n = b ? (1, S::x) // S::x is not odr-used here
: f(S::x); // S::x is odr-used here, so
// a definition is required
Run Code Online (Sandbox Code Playgroud) 请考虑C++ 14中[namespace.memdef]/3中的示例中的以下代码:
// Assume f and g have not yet been declared.
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() { …Run Code Online (Sandbox Code Playgroud) §3.5[basic.link]/3(我的重点):
具有命名空间作用域(3.3.6)的名称具有内部链接(如果它的名称)
(3.1) - 显式声明为static的变量,函数或函数模板; 要么,
(3.2) - 一个非易失性变量,显式声明为const或constexpr,既未显式声明为extern,也未声明为具有外部链接 ; 要么
(3.3) - 匿名工会的数据成员.
我认为(3.2)中粗体字符中的短语是多余的,除非有人能给出一个显式声明const但未声明的变量的例子extern,以及之前声明external linkage的变量,以及结果变量具有的变量external linkage.
c++ ×9
c++14 ×8
linkage ×2
c++11 ×1
declaration ×1
extern ×1
friend ×1
lookup ×1
namespaces ×1
templates ×1