简体   繁体   English

是否可以使用模板 class X 的 X 类型的 static constexpr 成员?

[英]Is it possible to have a static constexpr member with type X of template class X?

I once had 4 classes for 4 different RGB implementations (rgb, rgba, rgbf32, rgbaf32).我曾经有 4 个类用于 4 种不同的 RGB 实现(rgb、rgba、rgbf32、rgbaf32)。 Each class had a member color, and the code worked perfectly fine:每个 class 都有一个成员颜色,并且代码工作得非常好:

struct rgb {
    std::uint8_t r;
    std::uint8_t g;
    std::uint8_t b;

    const static rgb red;
};
constexpr rgb rgb::red = rgb{ 255, 0, 0 };

int main() {
    constexpr auto red = rgb::red;
}

I had 4 times the code length because of this, so I decided to combine them into one templated class:因此,我的代码长度增加了 4 倍,因此我决定将它们组合成一个模板 class:

#include <cstdint>
#include <type_traits>
#include <array>

template<bool f32, bool alpha>
using rgb_content =
    std::conditional_t<(!f32 && !alpha), std::array<std::uint8_t, 3>,
    std::conditional_t<(!f32 &&  alpha), std::array<std::uint8_t, 4>,
    std::conditional_t<( f32 && !alpha), std::array<float, 3>,
                                         std::array<float, 4>>>>;

template<bool f32, bool alpha>
struct rgb {
    rgb_content<f32, alpha> color;

    constexpr static auto get_red() {
        return rgb { f32 ? 1 : 255, 0, 0 };
    }

    const static rgb<f32, alpha> red;
};

template<bool f32, bool alpha>
const rgb<f32, alpha> rgb<f32, alpha>::red = rgb<f32, alpha>::get_red();

int main() {
    constexpr auto red = rgb<0, 0>::red;
}

I no longer get the static member red to work with this template class ( godbolt ):我不再让 static 成员red与此模板 class (天螺栓)一起工作:

error C2131: expression did not evaluate to a constant

I tried switching around constexpr and other keywords, but no success.我尝试切换constexpr和其他关键字,但没有成功。 The only solution I found was naming all possibilities:我找到的唯一解决方案是命名所有可能性:

constexpr rgb<0, 0> rgb<0, 0>::red = rgb<0, 0>::get_red();
constexpr rgb<0, 1> rgb<0, 1>::red = rgb<0, 1>::get_red();
constexpr rgb<1, 0> rgb<1, 0>::red = rgb<1, 0>::get_red();
constexpr rgb<1, 1> rgb<1, 1>::red = rgb<1, 1>::get_red();

int main() {
    using u8 = std::uint8_t;

    static_assert(rgb<0, 0>::red.color == std::array{(u8)255u, (u8)0u, (u8)0u});
    static_assert(rgb<0, 1>::red.color == std::array{(u8)255u, (u8)0u, (u8)0u, (u8)0u});
    static_assert(rgb<1, 0>::red.color == std::array{1.0f, 0.0f, 0.0f});
    static_assert(rgb<1, 1>::red.color == std::array{1.0f, 0.0f, 0.0f, 0.0f});
}

but this only compiles with MSVC (see here ) and it's pretty unmaintanable.但这只能与 MSVC 一起编译(请参见此处),而且非常难以维护。


Is this even possible to implement?这甚至可以实施吗? Do I have to use constexpr static member functions like red() instead?我是否必须使用像red()这样的constexpr static成员函数?

constexpr auto red = rgb<0, 0>::red;

rgb<0,0>::red is not a constexpr value, this doesn't work. rgb<0,0>::red不是constexpr值,这不起作用。

This compiles for me, with gcc 12:这为我编译,gcc 12:

template<bool f32, bool alpha>
struct rgb {
    rgb_content<f32, alpha> color;

    constexpr static auto get_red() {
        return rgb { f32 ? 1 : 255, 0, 0 };
    }

    constexpr static rgb<f32, alpha> red=get_red();
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM