Strange behavior with constexpr static member variable

前端 未结 2 1017
一生所求
一生所求 2020-12-03 22:03

This is a follow up question to Undefined reference to static constexpr char[][].

The following program builds and runs fine.

#include 

        
相关标签:
2条回答
  • 2020-12-03 22:15

    In addition to the information provided by @hvd in his answer...

    From the C++ Draft Standard N3337 (emphasis mine):

    9.4.2 Static data members

    3 If a non-volatile const static data member is of integral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment- expression is a constant expression (5.19). A static data member of literal type can be declared in the class definition with the constexpr specifier; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. [ Note: In both these cases, the member may appear in constant expressions. — end note ] The member shall still be defined in a namespace scope if it is odr-used (3.2) in the program and the namespace scope definition shall not contain an initializer.

    Given that A::data is odr-used in the expression A::data[0], as per the standard, it shall be defined in a namespace scope. The fact that g++ is able to successfully create a program without A::data being defined in a namescpace scope does not make the program right. To be standards compliant, A::data shall be defined.

    0 讨论(0)
  • 2020-12-03 22:27

    The standard does not require any diagnostics for a failure to provide a definition where one is required.

    3.2 One definition rule [basic.def.odr]

    4 Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required. [...]

    This means implementations are allowed to optimise away accesses to such variables, and that's what's happening in your first case with GCC.

    Both GCC and clang have decided that they prefer a consistent user experience, where error messages about missing definitions do not depend on the optimisation level. Usually, that means that any missing definition causes an error message. However, in this case, GCC is doing some minimal optimisation even at -O0, avoiding the error.

    But the program is an error either way, because even A::dict[0] is an ODR-use:

    3.2 One definition rule [basic.def.odr]

    3 A variable x whose name appears as a potentially-evaluated expression ex is odr-used by ex unless applying the lvalue-to-rvalue conversion (4.1) to x yields a constant expression (5.19) that does not invoke any non-trivial functions and, if x is an object, ex is an element of the set of potential results of an expression e, where either the lvalue-to-rvalue conversion (4.1) is applied to e, or e is a discarded-value expression (Clause 5). [...]

    The use of A::dict doesn't involve lvalue-to-rvalue conversion, it involves the array-to-pointer conversion, so the exception doesn't apply.

    0 讨论(0)
提交回复
热议问题