C++:嵌套 std::conditionals

C++: nested std::conditionals

我有一个简单的图像结构,其中包含实际图像数据。它可以按不同的顺序存储。这是所用结构的简化:

template <typename T, size_t C>
struct Image
{
public:


private:
    enum class ColorOrder1
    {
        UNKNOWN,
        INTENSITY
    };
    enum class ColorOrder3
    {
        UNKNOWN,
        RGB,
        BGR
    };

    enum class ColorOrder4
    {
        UNKNOWN,
        RGBA,
        BGRA
    };

public:
    using ColorOrder =
        typename std::conditional<C == 4, ColorOrder4,
                                  std::conditional<C == 3, ColorOrder3, ColorOrder1>>::type;

    // ColorOrder colorOrder;                      // <---- This works fine
    ColorOrder colorOrder = ColorOrder::UNKNOWN;   // <---- This does not

    std::shared_ptr<const std::vector<T>> data;

    /* .. and more data. but not imported */
};

我试图根据 std::conditional 的通道数限制可能的颜色顺序。例如。如果我们只有一个通道图像,顺序不应该是 RGBA。这基本上有效。但是,如果我尝试将所有情况下的颜色顺序默认为 UNKNOWN,它就不会再编译了。尽管 UNKNOWN 存在于所有枚举中。我得到的结果错误是:


 error: ‘UNKNOWN’ is not a member of ‘Image<unsigned char, 3>::ColorOrder’ {aka ‘std::conditional<true, Image<unsigned char, 3>::ColorOrder3, Image<unsigned char, 3>::ColorOrder1>’}
     ColorOrder colorOrder = ColorOrder::UNKNOWN;

我假设我的嵌套 std::conditional 实际上失败了。如何正确写这个?

提前感谢您的任何反馈。

你错过了 ::type 的内部 std::conditional

using ColorOrder =
        typename std::conditional<C == 4,
                                  ColorOrder4,
                                  typename std::conditional<C == 3,
                                                            ColorOrder3,
                                                            ColorOrder1
                                                           >::type
                                  >::type;

或者在 C++14 中,

using ColorOrder =
        std::conditional_t<C == 4,
                           ColorOrder4,
                           std::conditional_t<C == 3, ColorOrder3, ColorOrder1>>;

.. 啊伙计,问完这个问题我很快就知道出了什么问题:

    using ColorOrder = typename std::conditional<
        C == 4, ColorOrder4,
        typename std::conditional<C == 3, ColorOrder3, ColorOrder1>::type>::type;

请注意我之前错过的附加 typename::type

我会以不同的方式做到这一点:

public:
    using PossibleOrders = std::tuple<void, ColorOrder1, void, ColorOrder3, ColorOrder4>;
    using ColorOrder = typename std::tuple_element<C, PossibleOrders>::type;

    ColorOrder colorOrder = ColorOrder::UNKNOWN;

Live demo

IMO 这种方法更灵活,也更容易阅读。

顺便说一句,std::shared_ptr<const std::vector<T>> 的使用有点奇怪。可能您想在图像之间共享数据。