初始化类模板的静态constexpr成员变量

Initialize static constexpr member variable of class template

本文关键字:constexpr 成员 变量 静态 初始化      更新时间:2024-09-28

情况如下:具有模板参数int N的类Foo具有静态成员变量float valval的值对应于N,并且从未改变,所以我希望它是constexpr

我知道初始化静态constexpr成员变量的常用方法是:

// ok, but not what I want
template <int N>
struct Foo {
static constexpr float val { 0.0f };
};
template <int N>
constexpr float Foo<N>::val;

但是因为val是在类作用域内初始化的,所以我不能为不同的N指定不同的val

如果val不是constexpr而是const,则此操作有效:

// ok, but not what I want
template <int N>
struct Foo {
static const float val;
};
template <>
const float Foo<0>::val = 3.14f;
template <>
const float Foo<1>::val = 0.1f;

但是我不能使用constexpr float val = Foo<0>::val;,因为Foo<0>::val不是一个常量表达式。

因此,我想要实现的目标如下:

// the thing I want, but error
template <int N>
struct Foo {
static constexpr float val;
};
template <>
constexpr float Foo<0>::val = 3.14f;
template <>
constexpr float Foo<1>::val = 0.1f;

但编译器抱怨道:

错误:constexpr静态数据成员"val"的声明需要初始值设定项

如果我为val(static constexpr float val { 0.0f };(添加一个初始值设定项,编译器会说:

错误:"Foo<0>:val'
错误:'Foo<1>:val’

多么讽刺:D

我知道的一个变通方法是使用变量模板(C++14(:

// ok
struct Foo {
template <int N>
static constexpr float val { 0.0f };
};
template <>
constexpr float Foo::val<0> = 3.14f;
template <>
constexpr float Foo::val<1> = 0.1f;

目前,这是意料之中的事。但如果Foo中的其他成员(变量或函数(仍然需要模板参数(即Foo需要是类模板(,则此解决方案不适用。

你知道吗?使用低于C++20的C++标准的解决方案是首选(C++20对我的项目来说太新了(。

您可以将类模板专门化为

template <int N>
struct Foo {
static constexpr float val { 0.0f };
};
template <>
struct Foo<0> {
static constexpr float val { 3.14f };
};
template <>
struct Foo<1> {
static constexpr float val { 0.1f };
};

或者制作一个用于初始化的函数助手。

template <int N>
struct Foo {    
static constexpr float get_val() {
if constexpr (N == 0) return 3.14f;
else if constexpr (N == 1) return 0.1f;
else return 0.0f;
}
static constexpr float val { get_val() };
};