0

Given a toy struct with a default constructor like this one:

struct RGB {
    unsigned char r, g, b;

    RGB() 
        :r(0), g(0), b(0) {}
};

How do I initialise one to a specific colour, assuming I don't have access to the source code to add my own constructor.

I don't understand fully why these don't work:

// OK, I can sort-of accept this one
RGB red = {255, 0, 0};

// Not shorthand for green.r=0, green.g=255, green.b=0;?
RGB green = {.r = 0, .g = 255, .b = 0};

// I seem to be missing a constructor that accepts a list?
RGB blue{0, 0, 255};

Is there any other C++11 way to shorten the good old-fashioned:

RGB yellow;
yellow.r = 255;
yellow.g = 255;
yellow.b = 0;

Furthermore, how could I minimally modify the struct declaration to support any of the above, as well as having a default initialisation method.

Ken Y-N
  • 14,644
  • 21
  • 71
  • 114

2 Answers2

2

If you have no possibility to add default arguments to the struct's constructor, how about a helper function:

RGB makeRGB(unsigned char r, unsigned char g, unsigned char b)
{
    RGB result;
    result.r = r;
    result.g = g;
    result.b = b;
    return result;
}

Which can be used like so:

RGB red = makeRGB(255, 0, 0);

Return value optimization will take care of the temporary and provide a no-overhead solution unless you are using a terrible compiler.


The ideal solution would be modifying the default constructor to take optional arguments:

struct RGB {
    unsigned char r, g, b;

    explicit RGB(unsigned char r, unsigned char g, unsigned char b) 
        :r(r), g(g), b(b) {}
    RGB() : RGB(0, 0, 0) {}
};

Which can be used like you would expect:

RGB red(255, 0, 0);
RGB green{0, 255, 0};
RGB blue;
blue.b = 255;

Live demo here.

Community
  • 1
  • 1
rubenvb
  • 74,642
  • 33
  • 187
  • 332
  • 1
    The "ideal solution" isn't so ideal - it defines an implicit conversion from `unsigned char` to `RGB`. – T.C. Jul 20 '16 at 21:43
  • Thanks, I was probably overthinking the problem. I should submit a bug report/change request to the project that generates the problematic headers to see if they can make slightly more initialisation-friendly constructors. – Ken Y-N Jul 20 '16 at 23:37
0

Given

struct color
{
color(std::initializer_list<float> list) = delete;
float r, g, b;
};
  1. color c = {1,2,3} and color c {1,2,3} are the same.
  2. syntax like color c = {.r = 0, .g = 255, .b = 0}; is specific to C programming language, not C++.
  3. color c = {1,2,3}; is perfectly fine in C++11. It is called aggregate initialization. And it does even override explicit constructor from initializer_list. Link describes how to explicitly delete it.
  4. Constructor from initializer_list can be explicitly called by color c({1,2,3})
Andrei R.
  • 2,374
  • 1
  • 13
  • 27