初始化class模板的static constexpr成员变量
Initialize static constexpr member variable of class template
情况如下:带有模板参数 int N
的 class Foo
有一个静态成员变量 float val
。 val
的值对应于 N
并且永远不会改变,所以我希望它是 constexpr
.
我知道初始化static 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
在 class 范围内 初始化 ,我不能为不同的 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;
但是编译器抱怨:
error: declaration of constexpr static data member 'val' requires an initializer
如果我为 val
(static constexpr float val { 0.0f };
) 添加初始化程序,编译器会说:
error: duplicate initialization of 'Foo<0>::val'
error: duplicate initialization of 'Foo<1>::val'
多么讽刺 :D
我知道的解决方法是使用 variable template (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
需要是class模板),则此解决方案不适用。
对此有什么想法吗?使用低于 C++20 的 C++ 标准的解决方案是首选(C++20 对我的项目来说太新了)。
您可以将 class 模板特化为
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() };
};
情况如下:带有模板参数 int N
的 class Foo
有一个静态成员变量 float val
。 val
的值对应于 N
并且永远不会改变,所以我希望它是 constexpr
.
我知道初始化static 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
在 class 范围内 初始化 ,我不能为不同的 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;
但是编译器抱怨:
error: declaration of constexpr static data member 'val' requires an initializer
如果我为 val
(static constexpr float val { 0.0f };
) 添加初始化程序,编译器会说:
error: duplicate initialization of 'Foo<0>::val'
error: duplicate initialization of 'Foo<1>::val'
多么讽刺 :D
我知道的解决方法是使用 variable template (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
需要是class模板),则此解决方案不适用。
对此有什么想法吗?使用低于 C++20 的 C++ 标准的解决方案是首选(C++20 对我的项目来说太新了)。
您可以将 class 模板特化为
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() };
};