Vic*_*ian 2 c++ templates constexpr c++14 c++17
情况如下:Foo
带有模板参数的类int N
有一个静态成员变量float val
。的值val
对应于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;
Run Code Online (Sandbox Code Playgroud)
但是因为val
是在类范围内初始化的,所以我不能val
为不同的N
.
如果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;
Run Code Online (Sandbox Code Playgroud)
但后来我不能使用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;
Run Code Online (Sandbox Code Playgroud)
但是编译器抱怨:
错误: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;
Run Code Online (Sandbox Code Playgroud)
目前,这按预期工作。但如果其他成员(变量或函数)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 };
};
Run Code Online (Sandbox Code Playgroud)
或者制作一个用于初始化的函数助手。
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() };
};
Run Code Online (Sandbox Code Playgroud)