Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initialize object containing C-style array as member variable (C++)

Consider the following code:

struct Color  // This struct can't be modified
{
    double grey;
    double rgb[3];
};

int main()
{
    double myRGB[3] = {2, 6, 9};

    Color c = {10, myRGB}; // This line doesn't work

    return 0;
}

How can I initialize a Color object in one line?

In my real case scenario, Color struct can't be change (for example, to use std::array instead of a C-style array).

like image 287
Gaetan Avatar asked Nov 05 '18 14:11

Gaetan


2 Answers

Since Color is an aggregate you can use aggregate initialization and put the array initializer directly in the braces like

Color c = {10, {2, 6, 9}};

If you have to initialize c with an array, since it is small, you can just unroll it like

Color c = {10, {myRGB[0], myRGB[1], myRGB[2]}};
like image 92
NathanOliver Avatar answered Oct 22 '22 16:10

NathanOliver


Supposing that there is a need to use an intermediate array, here is how one can do it:

#include <utility>
#include <cstddef>

struct Color  //this struct can't be modified
{
    double grey;
    double rgb[3];
};

template<size_t N, size_t... IX>
auto make_c_impl(double grey, double (&rgb)[N], std::index_sequence<IX...>) {
    static_assert(sizeof(rgb) == sizeof(Color::rgb), "Arrays sizes must match!");
    return Color{grey, {rgb[IX]...}};
}

template<size_t N>
auto make_c(double grey, double (&rgb)[N]) {
    return make_c_impl(grey, rgb, std::make_index_sequence<N>{});
}
double myRGB[3] = {2, 6, 9};

Color c = make_c(10, myRGB); //this line now works

Note, that this code will not actually produce any unnecessary copying with any level of optimization.

like image 27
SergeyA Avatar answered Oct 22 '22 15:10

SergeyA