c++arraysstructinitializationunions

How to initialize an array of structs containing union in C++?


I have been struggling with initialization of an array containing struct members with union.
Let's say I have following declarations in C++

enum class FilterType { kLowPass, kAverage };
    
enum class FilterLowPassConfig {
    k1kHzLowPass = 0,
    k10kHzLowPass = 1,
    k20kHzLowPass = 2,
    k40kHzLowPass = 3
};
    
enum class FilterAverageConfig {
    kWindowSize256 = 0,
    kWindowSize128 = 1,
    kWindowSize64 = 2,
    kWindowSize32 = 3
};
    
union FilterConfig {
    FilterLowPassConfig low_pass_config;
    FilterAverageConfig average_config;
};
    
struct FilterSelect
{
    FilterType filter_type;
    FilterConfig filter_config;
};

Now I define an array:

FilterSelect filter_select[2];

Is it possible to initialize the array filter_select with brace-enclosed initializer list?


Solution

  • You can use std::variant instead of a C style union.

    In modern C++ std::variant is recommended in general (see more info here), and with it you can do:

    #include <variant>
    
    enum class FilterType { kLowPass, kAverage };
    
    enum class FilterLowPassConfig {
        k1kHzLowPass = 0,
        k10kHzLowPass = 1,
        k20kHzLowPass = 2,
        k40kHzLowPass = 3
    };
    
    enum class FilterAverageConfig {
        kWindowSize256 = 0,
        kWindowSize128 = 1,
        kWindowSize64 = 2,
        kWindowSize32 = 3
    };
    
    using FilterConfig = std::variant<FilterLowPassConfig, FilterAverageConfig>;
    
    struct FilterSelect
    {
        FilterType filter_type;
        FilterConfig filter_config;
    };
    
    int main() 
    {
        [[maybe_unused]] FilterSelect filter_select[2] = 
        { { FilterType::kLowPass,  FilterLowPassConfig{FilterLowPassConfig::k1kHzLowPass}},
          { FilterType::kAverage,  FilterAverageConfig{FilterAverageConfig::kWindowSize256}} };
    }
    

    Live demo

    An additional recommendation is to use std::array insread of a C style array:

    #include <array>
    
    // ...
    
    int main() 
    {
        [[maybe_unused]] std::array<FilterSelect, 2> filter_select =
        { FilterSelect{FilterType::kLowPass, FilterLowPassConfig{FilterLowPassConfig::k10kHzLowPass}},
          FilterSelect{FilterType::kLowPass, FilterLowPassConfig{FilterLowPassConfig::k10kHzLowPass}} };
    }
    

    Live demo with std::array