Is a constexpr array necessarily odr-used when subscripted?

前端 未结 3 1259
情深已故
情深已故 2020-11-28 11:03

Given the following code:

struct A { static constexpr int a[3] = {1,2,3}; };

int main () {
  int a = A::a[0];
  int b  [A::a[1]];
}

is

3条回答
  •  一个人的身影
    2020-11-28 11:28

    Yes, A::a is odr-used.

    In C++11, the relevant wording is 3.2p2 [basic.def.odr]:

    [...] A variable whose name appears as a potentially-evaluated expression is odr-used unless it is an object that satisfies the requirements for appearing in a constant expression (5.19) and the lvalue-to-rvalue conversion (4.1) is immediately applied. [...]

    The name of the variable A::a appears in the declaration int a = A::a[0], in the full-expression A::a[0], which is a potentially-evaluated expression. A::a is:

    • an object
    • that satisfies the requirements for appearing in a constant expression

    However, the lvalue-to-rvalue conversion is not immediately applied to A::a; it is applied to the expression A::a[0]. Indeed, lvalue-to-rvalue conversion may not apply to an object of array type (4.1p1).

    So A::a is odr-used.


    Since C++11, the rules have been broadened somewhat. DR712 Are integer constant operands of a conditional-expression "used?" introduces the concept of the set of potential results of an expression, which allows expressions such as x ? S::a : S::b to avoid odr-use. However, while the set of potential results respects such operators as the conditional operator and comma operator, it does not respect indexing or indirection; so A::a is still odr-used in the current drafts for C++14 (n3936 as of date).

    [I believe this is a condensed equivalent to Richard Smith's answer, which however does not mention the change since C++11.]

    At When is a variable odr-used in C++14? we discuss this issue and possible wording changes to section 3.2 to allow indexing or indirecting an array to avoid odr-use.

提交回复
热议问题