constexpr of static tuple class member has linker error

后端 未结 2 1796
[愿得一人]
[愿得一人] 2021-01-18 16:10

I have the following code:

#include 
#include 

class T
{
    public:
        using Names = std::tuple

        
2条回答
  •  一个人的身影
    2021-01-18 16:53

    A declaration of a static data member in class is never a definition1.
    A definition is necessary whenever a variable is odr-used2. std::get<> takes arguments per reference, and binding a variable to a reference odr-uses it immediately3.

    Simply define names outside:

    constexpr T::Names T::names; // Edit: This goes *outside* the class "as is"!
    

    Demo.


    1) [basic.def]/2:

    A declaration is a definition unless [..] it declares a static data member in a class definition (9.2, 9.4)

    2) [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.

    3) According to [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).

    Here the id-expression T::names refers to the variable in question. The only superexpression e that contains all the potential results of T::names is T::names itself, because the set of potential results of a function call, i.e. std::get<0>(T::names), is empty. However, the lvalue-to-rvalue conversion is clearly not applied, and the value of T::names is also clearly not discarded (as it is passed to a function).
    Thus it is odr-used and requires a definition.

提交回复
热议问题