Strange behaviour of structures in C++ [part 1]

Consider:

struct box
{
    int array[3];
};

int main()
{
    box a = {1};
}

If the above works in C++ then why doesn't the following work?

struct box
{
    int simple_int;
};

int main()
{
    box b = 2;
}

What is the reason?


Solution 1:

Properly, the former would use box a = { { 1 } }, so that you have one set of braces for each aggregate. The outer set of braces is for the structure, and the inner set is for the array. However, the language allows you to omit inner braces.

In the latter, there are no inner braces to omit. You are not allowed to omit outer braces; you must have at least one set of braces to distinguish a list of initializers for an aggregate. In a sense, the braces say “Here is a list of things to put inside the aggregate.” When you write box b = 2, the compiler does not know you want to put 2 inside the aggregate. Instead, it looks like you are trying to initialize the b object (rather than part of it) to 2. So the compiler tries to find a constructor or a conversion that changes a 2 into a box. When this fails, you get an error.

Solution 2:

It doesn't work because your syntax is wrong. You can add support for b = 2 with an implicit constructor, if that is what you want.

box b = {2}; // correct syntax with no constructor

Or

struct box
{
    // implicit constructor
    box(int i) : i(i) {}
    int i;
};

box b(2);
box c = 2;

Or

struct box
{
    explicit box(int i) : i(i) {}
    int i;
};

box b(2);
box c = 2; // disallowed