C++14中什么时候使用变量odr-?

cld4siwp  于 2023-10-21  发布在  其他
关注(0)|答案(1)|浏览(93)

C14草案(N3936)在§3.2/3中指出:
一个变量x,其名称作为一个可能求值的表达式ex出现,是odr使用的,除非将左值到右值的转换(4.1)应用于x产生一个不调用任何非平凡函数的常量表达式(5.19),并且如果x是一个对象,ex是表达式e的潜在结果集合中的一个元素,其中左值到右值的转换(4.1)应用于e,或者e是一个带值的表达式(第5章)。
这对我来说没有任何意义:表达式e是否是 * 带值表达式 * 取决于e使用的上下文。在 expression-statement(第6.2节)中使用的每个表达式都是一个 * 带值表达式 *。如果 *lvalue-to-rvalue转换 * 应用于e,也取决于e所使用的上下文。
此外,一个表达式在另一个表达式的 * 潜在结果 * 集中意味着什么。人们需要一个表达式相等的概念来确定集合的成员资格。但我们没有“参考透明度”,所以我看不出这是如何实现的。
C
11为什么会变成C++14?这应该如何解释?照目前的情况看,这说不通。

w41d8nur

w41d8nur1#

odr使用目的

非正式地,变量的 * odr-use * 表示以下内容:
如果程序中任何地方的任何表达式接受对象的地址或直接将引用绑定到对象,则必须定义此对象。

最新草案中的说明

在最新版本的规范中,第3.2节已得到澄清(参见Draft C++14 on GitHub):
2一个表达式可能被求值,除非它是一个未求值的操作数(第5条)或其子表达式。表达式e的潜在结果集定义如下:

  • 如果e是一个id表达式(5.1.1),则集合只包含e
  • 如果e是类成员访问表达式(5.2.5),则集合包含对象表达式的潜在结果。
  • 如果e是一个指向成员的指针表达式(5.5),其第二个操作数是一个常量表达式,则集合包含对象表达式的潜在结果。
  • 如果e的形式为(e1),则集合包含e1的可能结果。
  • 如果e是一个glvalue条件表达式(5.16),则该集合是第二个和第三个操作数的潜在结果集合的并集。
  • 如果e是一个逗号表达式(5.18),则集合包含右操作数的可能结果。
  • 否则,该集合为空。

[注意:这个集合是一个(可能为空)id表达式的集合,每个id表达式要么是e,要么是e的子表达式。
[示例:在下面的示例中,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
  • 结束示例] -结束注解]
    3一个变量x,如果它的名字作为一个可能求值的表达式ex出现,那么它被ex**odr使用,除非将左值到右值的转换(4.1)应用于x,产生一个不调用任何非平凡函数的常量表达式(5.19),并且如果x是一个对象,那么ex是表达式e的一组可能结果的元素,其中左值到右值的转换(4.1)应用于e,或者e是一个带值的表达式(第5章)。

C++11是什么情况?

§3.2/2在C++11中是这样写的:
一个表达式可能被求值,除非它是一个未求值的操作数(条款5)或其子表达式。一个变量的名字作为一个可能被求值的表达式出现,除非它是一个满足出现在常量表达式(5.19)中的要求的对象,并且左值到右值的转换(4.1)被**立即 * 应用。
这些措辞的问题是DR 712。请考虑以下示例:

struct S {
  static const int a = 1;
  static const int b = 2;
};
int f(bool x) {
  return x ? S::a : S::b;
}

由于S::aS::b是左值,因此条件表达式x ? S::a : S::b也是左值。这意味着左值到右值的转换不是立即应用于S::aS::b,而是应用于条件表达式的结果。这意味着根据C11的措辞,这些静态数据成员是odr使用的,需要定义。但实际上只使用值,因此不需要定义静态数据成员-声明就足够了。C14草案的新措辞解决了这个问题。

新措辞是否解决了所有问题?

在下面的例子中,变量S::a仍然是odr使用的:

struct S { static constexpr int a[2] = {0, 1}; };
void f() {
    auto x = S::a[0];
}

因此,我提交了一个新的问题,在§3.2/2中添加以下项目:

  • 如果eE1[E2]形式的glvalue下标表达式(5.2.1),则集合包含E1的潜在结果。

相关问题