gpt4 book ai didi

c++ - 静态 constexpr 模板成员在专门化时给出 undefined reference

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:17:27 37 4
gpt4 key购买 nike

下面的代码给出了一个 undefined reference 链接错误:

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

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

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

但我不知 Prop 体原因。

是否可以在不专门化整个模板的情况下定义数据成员?

明确一点:此代码编译正常,但给出链接器错误( undefined reference )。

最佳答案

Is it possible to define a data-member without [specializing] the whole template?

static 类模板的数据成员允许显式特化([temp.expl.spec]),但是如果你想这样做,你不能已经在类模板 (class.static.data) 中为成员指定了初始值设定项。也就是说,

如果我们用 const 替换 constexpr,这段代码就可以了:

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;

您可以看到不同之处在于我们为主模板初始化变量的位置。

现在,如果我们希望用 constexpr 替换 const,那么我们需要提供一个初始化器(class.static.data ):

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

所以我们最终会遇到这种奇怪的情况,我们可以特化 static 成员,但如果它是 constexpr 就不行,因为 constexpr 需要一个初始值设定项。恕我直言,这是该标准的一个缺点。

但是,似乎并非所有现代编译器都同意。

gcc 8.0.0 按原样编译(但不链接)您的代码(错误),但是如果您为特化添加初始化程序,它会提示重复初始化(正确)。

clang 6.0.0 不会按原样编译代码(正确),但是当您添加初始化程序时它可以顺利运行(错误,但这可能是标准应该规定的)

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;
// ...
};

在 C++17 及更高版本中,我们可以使用 constexpr if避免需要专门化我们的特征类:

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);
}

关于c++ - 静态 constexpr 模板成员在专门化时给出 undefined reference ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47886481/

37 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com