我相信[namespace.memdef]/1的新措辞试图解释两个声明using M::g;和void g();命名空间之间的冲突X,但我无法理解这个新措辞与暗示冲突之间的关系.
命名空间中的
N声明(不包括嵌套作用域中的声明),其declarator-id为unqualified-id([dcl.meaning]),其class-head-name(Clause [class])或enum-head-name ([dcl] .enum])是一个标识符,或者其详细类型说明符 的格式为class-key attribute-specifier-seq opt identifier([dcl.type.elab]),或者是一个opaque-enum-declaration,声明(或重新声明)其不合格的身份或标识符作为成员N.[注意:模板的显式实例化([temp.explicit])或显式特化([temp.expl.spec])不会引入名称,因此可以在封闭名称空间的成员中使用unqualified-id声明如果主模板在内联命名空间中声明,则设置. - 尾注] [示例:Run Code Online (Sandbox Code Playgroud)namespace X { void f() { /* ... */ } // OK: introduces X?::?f() namespace M { void g(); // OK: introduces X?::?M?::?g() } using M::g; void g(); // error: conflicts with …
这基本上是我先前关于DR 712的问题的延续.让我首先解释为什么我坚持要看一些可以被认为是旧的东西,如C++ 11标准,但我的问题是该部分[基本的. def.odr]在C++ 11中已经很难理解了,在我深入研究当前草案中的相同部分之前我想完全覆盖它,在我看来,这个部分更加复杂.
Austing Hasting的前一个问题的答案很好,但我仍然有一点在C++ 11的[basic.def.odr]/2中不明确.考虑这个小而简单的例子:
const int i = 1;
int main()
{
int j = i;
}
Run Code Online (Sandbox Code Playgroud)
从[basic.def.odr]/2在C++ 11 i是未 odr-used在int j = i;作为i是满足用于以恒定表达和左值到右值转换出现被立即应用到要求的对象i.这对我来说没有多大意义,正如i在声明中使用的int j = i;那样,在这里显示的略微修改的代码中可以看出,我强制变量i不被编译的代码优化.
当然,上面的推理肯定有问题,因为我不相信C++ 11在这么简单的例子中可能是错的.再一次,我现在想念的是什么?
我在这里找到了这个例子.显然,片段中的注释是错误的,因为变量S::x是由表达式使用的&S::x.
struct S { static const int x = 1; };
void f() { &S::x; } // discarded-value expression does not odr-use S::x
int main(){
f();
}
Run Code Online (Sandbox Code Playgroud)
查看实例
我理解编译器不需要发出这样的错误,因为[basic.def.odr]/10说"不需要诊断".但是为什么链接器不会发出关于未定义变量的错误S::x,就像在下面的代码中那样?
#include<iostream>
struct S { static const int x = 1; } s;
int main() {
std::cout << &s.x << '\n';
}
Run Code Online (Sandbox Code Playgroud)
查看实例.
[lex.ccon]包含c-char的以下定义:
c-char:
源字符集的任何成员,
但单引号’,反斜杠\或换行符
转义序列通用字符名称除外
鉴于新行字符C是转义序列\n,上面的定义中是否存在矛盾?
PS:请注意,C++标准并没有真正定义什么是换行符.
下面你会在[class]/1中找到语法生成类头的定义:
class-head:
class-key attribute-specifier-seq opt class-head-name class-virt-specifier opt base-clause opt
class-key attribute-specifier-seq opt base-clause opt
在段落的末尾,您将找到以下内容:
一类符,其类头省略了类头名 定义了一个无名类.[注意:一个未命名的类因此不能是 最终的. - 尾注]
从上面开始,我收集了一个命名类的语法,即一个带有类头名的类,由上面的第一个定义给出,而一个未命名的类的语法由第二个定义给出.
一个简单的问题:不可能用第一个替换上面的两个定义,只需用class-head-name opt替换class-head-name就可以了?
或者更清楚.以下是不可能为class-head替换上面的定义?
class-head:
class-key attribute-specifier-seq opt class-head-name opt class-virt-specifier opt base-clause opt