The static member of the constexpr pattern gives undefined -reference when specialized

The following code provides a link to an undefined link:

template<int>
struct X {
    static constexpr int x = 0;
};

template<>
constexpr int X<1>::x;

int main() 
{   
    return X<1>::x;
}

But I don’t know exactly why.

Is it possible to define a data item without specializing the entire template?

To be clear: this code compiles fine, but gives a linker error (undefined -reference).

+4
source share
3 answers

Is it possible to define a data item without [specializing] the entire template?

statictemplate data members are allowed to be explicitly specialized ([temp.expl.spec]), however, if you want to do this, you can no longer specify the initializer for the member in the class template (class.static.data). I.e

constexpr const, :

template<int>
struct X {
    static const int x;
};

template<int I>
const int X<I>::x = 0;

template<>
const int X<1>::x = 1;

:

template<int>
struct X {
    static const int x = 0;
};

template<>
const int X<1>::x = 1;

, , .

, const constexpr, , (class.static.data):

A static literal constexpr; , - -, -,

, , static, constexpr, constexpr . IMHO .

, , .

gcc 8.0.0 ( ) (), , ().

clang 6.0.0 as-is (), , (, , , , )

MSVC 19.00.23506 (), , ( ) ().

, Traits:

template<int>
struct X_Traits{
    static constexpr int value = 0;
};

template<>
struct X_Traits<1>{
    static constexpr int value = 1;
};

template<int I>
struct X {
    static constexpr int x=X_Traits<I>::value;
    // ...
};

++ 17 constexpr, , :

template<int I>
struct X_Traits{
    static constexpr int get_value(){
        if constexpr(I==1){
            return 1;
        }else{
            return 0;
        }
    }
};

template<int I>
struct X {
    static constexpr int x=X_Traits<I>::get_value();
    // ...
};

int main(){
    static_assert(X<0>::x == 0);
    static_assert(X<1>::x == 1);
}
+3

"" - . [temp.expl.spec]/13:

- ; . [: , , -INIT-:

template<> X Q<int>::x;                         // declaration
template<> X Q<int>::x ();                      // error: declares a function
template<> X Q<int>::x { };                     // definition

- ]

, X<1>::x , . , undefined.

, , , . constexpr, . .

+4

like this.

template<int i>
struct X {
    static constexpr int x = i==0?2:10;
};

int main() 
{   
    return X<1>::x;
}

note that you do not need to define it outside the class.

+2
source

Source: https://habr.com/ru/post/1691037/


All Articles