Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write proper std::initializer_list constructor

Consider following code:

#include <iostream>
#include <vector>

struct C {
    std::vector<int> a;
    std::string b;
    bool c;
};

void printC(const C &c) {
    // ...
}

int main() {
    printC({
        { 1, 2, 3 },
        "ehlo",
        false
    });
}

This works, because compiler can generate proper constructor for me. But if I change struct C to this:

struct C {
    std::vector<int> a;
    std::string b;
    bool c;

    C() {
        c = false;
    }
};

The printC call stops working because compiler stops generating appropriate constructor. I've tried to write myself a constructor using std::initializer_list but failed.

So the question is - How to write constructor that will make the above code compile and work again?

like image 590
doomista Avatar asked Dec 20 '18 07:12

doomista


People also ask

What is Initializer_list constructor?

A std::initializer_list object is automatically constructed when: a braced-init-list is used to list-initialize an object, where the corresponding constructor accepts an std::initializer_list parameter.

What is std :: Initializer_list?

std::initializer_list a braced-init-list is used in list-initialization, including function-call list initialization and assignment expressions. a braced-init-list is bound to auto, including in a ranged for loop.

What is constructor initializer list in C++?

Initializer List is used in initializing the data members of a class. The list of members to be initialized is indicated with constructor as a comma-separated list followed by a colon. Following is an example that uses the initializer list to initialize x and y of Point class.

How do you initialize a class member in C++?

There are two ways to initialize a class object: Using a parenthesized expression list. The compiler calls the constructor of the class using this list as the constructor's argument list. Using a single initialization value and the = operator.


1 Answers

I've tried to write myself a constructor using std::initializer_list but failed.

You don't need one. You just need a c'tor taking a vector, string and boolean:

C(std::vector<int> a, std::string b, bool c) 
  : a(std::move(a))
  , b(std::move(b))
  , c(c) {
}

Your code should now be well-formed again. Though now it incurs two move operations, while the original aggregate version could have initialized the elements of your object directly. It's something worth considering.

like image 152
StoryTeller - Unslander Monica Avatar answered Sep 22 '22 04:09

StoryTeller - Unslander Monica