使用初始化列表初始化固定数量的变量

时间:2014-12-16 10:01:20

标签: c++ c++11 initializer-list

我想用初始化列表初始化一个对象。问题是,初始化列表能够包含不可预测数量的元素,但我只需要为变量初始化。用户可以发送任意数量的列表元素,我只需要其中的四个。

我编写了以下代码,但对我来说看起来很长很慢。有没有更好的方法呢?

Pixel::Pixel(std::initializer_list<uint8_t> Channels)
{
    switch (Channels.size())
    {
        case 0:
            R = 0;
            G = 0;
            B = 0;
            A = 0;
            break;
        case 1:
            R = *(Channels.begin() + 0);
            G = 0;
            B = 0;
            A = 0;
            break;
        case 2:
            R = *(Channels.begin() + 0);
            G = *(Channels.begin() + 1);
            B = 0;
            A = 0;
            break;
        case 3:
            R = *(Channels.begin() + 0);
            G = *(Channels.begin() + 1);
            B = *(Channels.begin() + 2);
            A = 0;
            break;
        default:
            R = *(Channels.begin() + 0);
            G = *(Channels.begin() + 1);
            B = *(Channels.begin() + 2);
            A = *(Channels.begin() + 3);
    }
}

(注意:我知道这可以通过使用四个单独的参数传递R,G,B,A值来完成。但我的主要目的是学习如何使用初始化列表功能执行此操作。)

2 个答案:

答案 0 :(得分:4)

使用std::initialiser_list

时我能想到的最好的结果
struct Pixel
{
    Pixel(std::initializer_list<uint8_t> rgba)
    : _rgba { rgba }
    {
        switch(_rgba.size()) {

            case 0: _rgba.push_back(0);
            case 1: _rgba.push_back(0);
            case 2: _rgba.push_back(0);
            case 3: _rgba.push_back(0);
            case 4: break;
            default:
                throw std::invalid_argument { "" };
        }

    }

    std::vector<uint8_t> _rgba;
};

......但......

解决这个问题的正确方法可能就是:

struct Pixel
{
    Pixel(uint8_t r = 0, uint8_t g = 0, uint8_t b = 0, uint8_t a = 0)
    : R(r)
    , G(g)
    , B(b)
    , A(a)
    {}

    uint8_t R,G,B,A;
};

,因为

  1. 如果提供无效参数,则无法编译
  2. 效率最佳
  3. 对于维护代码的人来说,这是最不令人惊讶的解决方案
  4. 它自动支持呼叫站点
  5. 的initializer_list语法

    的示例:

    int main()
    {
        Pixel p1 { 10, 20, 5, 255 };
        Pixel p2 { 10, 20, 5 };
        Pixel p3 { 10, 20 };
        Pixel p4 { 10 };
        Pixel p5 { };
    
        Pixel pv1 ( 10, 20, 5, 255 );
        Pixel pv2 ( 10, 20, 5 );
        Pixel pv3 ( 10, 20 );
        Pixel pv4 ( 10 );
        Pixel pv5;
    
        return 0;
    }
    

答案 1 :(得分:3)

您可以按以下步骤重写切换:

Pixel::Pixel(std::initializer_list<uint8_t> Channels) : R(0), G(0), B(0), A(0)
{
    switch (Channels.size())
    {
        default: // Too many args
        case 4: A = *(Channels.begin() + 3); // No break: Follow next line
        case 3: B = *(Channels.begin() + 2); // No break: Follow next line
        case 2: G = *(Channels.begin() + 1); // No break: Follow next line
        case 1: R = *(Channels.begin() + 0);
        case 0: break;
    }
}