【问题标题】:Initialize static constexpr member variable of class template初始化类模板的静态 constexpr 成员变量
【发布时间】:2021-08-07 09:54:48
【问题描述】:

情况如下:带有模板参数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&lt;0&gt;::val;,因为Foo&lt;0&gt;::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::val'的重复初始化
错误:'Foo::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需要是类模板),则此方案不适用。

对此有任何想法吗?首选使用低于 C++20 的 C++ 标准的解决方案(C++20 对我的项目来说太新了)。

【问题讨论】:

    标签: c++ templates c++17 c++14 constexpr


    【解决方案1】:

    您可以将类模板特化为

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-10
      • 1970-01-01
      • 2011-03-14
      • 2017-01-15
      相关资源
      最近更新 更多