[basic.def.odr] / 2中的示例以以下句子开头:
In the following example, the set of potential results of the initializer of n contains the first S::x subexpression, but not the second S::x subexpression.
根据本段中的定义,我们如何推断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
最佳答案
我正在使用基于N4296的最新github草案。实际的C++ 14国际标准不包含此示例,也不包含项目符号的编号。这里相关的规范实际上是相同的。
我们在初始值设定项中分解表达式:b ? (1, S::x) : f(S::x)
表达式(1, S::x)
是int const
类型的左值。
表达式f(S::x)
是一个后缀表达式,是int const
类型的左值。
因此,表达式b ? (1, S::x) : f(S::x)
是int const
类型的左值。因此,它满足[basic.def.odr] p2.5,并且潜在结果集是子表达式(1, S::x)
和f(S::x)
的潜在结果集的并集。
对于第一个子表达式(1, S::x)
,我们通过p2.4去除括号。结果1, S::x
是逗号表达式。我们应用p2.6并获得S::x
。现在,应用p2.1并告诉我们,第一次出现是初始化程序可能结果集的一部分。
对于第二个子表达式f(S::x)
,仅适用p2.7。它的潜在结果集为空,因此它不会对初始化程序的潜在结果集添加任何内容。
至于S::x
的odr-use,[basic.def.odr] p3
A variable
x
whose name appears as a potentially-evaluated expressionex
is odr-used byex
unless applying the lvalue-to-rvalue conversion tox
yields a constant expression that does not invoke any non-trivial functions and, ifx
is an object,ex
is an element of the set of potential results of an expressione
, where either the lvalue-to-rvalue conversion is applied toe
, ore
is a discarded-value expression.
让我们将其分为几个步骤:表达式
x
中出现的ex
变量构成了odr-use,除非:ex
或x
会产生一个不调用任何非平凡函数的常数表达式”和ex
是表达式e
的潜在结果集的元素,并且以下任意一项成立:e
” e
是一个废弃值表达式” 请注意,第2点表示“是ANYt表达式
e
[其中e
满足某些要求的情况]的潜在结果集中的元素”,而不是“它是其中的所有表达式e
的一部分”。可以在std-discussion mailing list上找到更多讨论。将步骤应用于第二次出现的S::x
它是表达式
S::x
,f(S::x)
和b ? (1, S::x) : f(S::x)
的一部分。S::x
会产生不调用任何函数的常量表达式)和S::x
是潜在结果集的元素的唯一表达式是S::x
本身。它不是f(S::x)
的潜在结果的一部分。以下任一条件必须成立:S::x
绑定(bind)到f
的功能参数时未应用左值到右值转换)S::x
不是舍弃值表达式)该异常不适用,
S::x
通过其第二次出现而被使用。将步骤应用于第一次出现的S::x
它是表达式
S::x
,1, S::x
,(1, S::x)
和b ? (1, S::x) : f(S::x)
的一部分。S::x
会产生一个不调用任何函数的常量表达式)和S::x
的首次出现是初始化程序中所有表达式的潜在结果集中的一个元素。以下任一条件必须成立:S::x
,1, S::x
和(1, S::x)
。可以说它被应用于b ? (1, S::x) : f(S::x)
(见下文)初始化是否应用左值到右值转换尚不清楚。可以说,必须读取“左值表达式的值”,以便根据
int
类型的表达式来初始化int const
。如果遵循此假设,则将左值到右值转换应用于b ? (1, S::x) : f(S::X)
。 S::x
的首次出现是该表达式的潜在结果集中的一个元素(请参阅此答案的第一部分)。因此,上面的项目符号点3.0适用,并且在第一次出现时不使用S::x
。您可以在Q&A Does initialization entail lvalue-to-rvalue conversion? Is
int x = x;
UB?的初始化中找到很多有关左值到右值转换的信息。这里的情况可能会容易一些,因为rhs的类型为int const
。这可能需要限定转换,该转换需要一个prvalue操作数(这可能隐式调用从左值到右值的转换)。
关于c++ - 试图了解C++ 14(N4140)中的[basic.def.odr]/2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29997142/