简体   繁体   中英

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?

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.

Worth noting that in C++14 and later you can just use a default member initializer:

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

Also, aggregate initialization generates no constructors. It bypasses them entirely.

You can pass an instance of a std::initializer_list<int> like this:

#include <initializer_list>

struct C {
    /* Data members... */

    C(std::initializer_list<int> vecData, std::string str, bool flag) :
        a{vecData}, b{std::move(str)}, c{flag} {}
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM