Initialization of a class's struct with vector of structs in constructor's intialization list

228 Views Asked by At

I wonder how could I describe a constructor's initialization list in order to define a class's variable of a struct type containing vector of structs:

class Class {

public:

Class() : _list( {{3, 4}} ) {}
Class(List _l) : _list(_l) {}

struct Value {
    int a;
    int b;
};

struct List {
    vector<Value> values;
};

private:
List _list;

}


int main() {
    Class c( {{2, 4}} );
}

Let's assume that some kind of a backward compatibility could induce some benefits of such approach.

Since the code with a default constructor only Class() : _list( {{3, 4}} ) {} seemed to compile without errors, appending a Class(List _l : _list(_l) constructor brings:

error: expected ')' before '_values'| and a code with definition of an objects gives back:

error: no matching function for call to 'Class::Class(<brace-enclosed initializer list>, <brace-enclosed initializer list>)'|.

I've tried few ways to solve it, e.g. few different definitions of an initializing list, different ways of passing of an argument in the constructor or defining constructors of a struct List. Part of those seemed to bring the mentioned errors.

Finally, I wonder if such functionality could be possible to achieve in such way.

Thanks for help and advice in advance.

1

There are 1 best solutions below

0
AKL On

Just add one more brace-pair and it will be OK!:

Class() : _list( {{{3, 4}}} ) {}

And also:

Class c( {{{2, 4}}} );

Brace-enclosed construction is usually used to indicate brace-enclosed-initialization of the data members or construction of elements from a range.

The Value struct here can be initialized simply by {3,4} because it has 2 data members and no other constructor.
In case of std::vector however this type of construction is used to indicate set of elements that are going to be stored in the vector in its construction.
Finally for List, the brace-enclosed constructor can only take one data of the typestd::vector<Value> in order to use it to initialize the only data member values, which itself is of type std::vector<Value>.

Here each class needs a brace enclosed initializer. One for Value, one for std::vector<Value> and one for List. In case of Value there could be only 2 data inside the braces (the most inner braces). But for std::vector<Value> there can be one or more data of the type Value inside its braces. Finally for List there can only be one data inside its braces(the most outer braces).
For example:

Class() : _list( {{{3, 4}, {5, 6}}} ) {}

Is also OK and results in putting 2 data of the typeValue inside the vector!

Also in order to use member structs/classes in constructors declare them first:

class Class {
public:
    struct Value;
    struct List;
    Class() : _list( {{{3, 4}}} ) {}
    Class(List _l) : _list(_l) {}
    struct Value {
        int a;
        int b;
    };
    struct List {
        std::vector<Value> values;
    };
private:
    List _list;
};

In comparison, it would be OK to remove the braces for List If the class was defined like:

class Class {
public:
    struct Value;
    struct List;
    Class() : _list( {3, 4} ) {}
    Class(List _l) : _list(_l) {}
    struct Value {
        int a;
        int b;
    };
    struct List {
        Value values;
    };
private:
    List _list;
};

But that is because List (and also Value) does not have a user defined constructor and List only has one data member!

Good luck