如何编写正确的 std::initializer_list 构造函数

How to write proper std::initializer_list constructor

考虑以下代码:

#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
    });
}

这行得通,因为编译器可以为我生成合适的构造函数。但是,如果我将结构 C 更改为:

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

    C() {
        c = false;
    }
};

printC 调用停止工作,因为编译器停止生成适当的构造函数。我尝试使用 std::initializer_list 为自己编写一个构造函数,但失败了。

所以问题是 - 如何编写使上述代码再次编译和工作的构造函数?

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

你不需要一个。您只需要一个接受向量、字符串和布尔值的 c'tor:

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

您的代码现在应该再次合式了。虽然现在它会产生两个移动操作,而原始聚合版本可以直接初始化对象的元素。这是值得考虑的事情。

您可以像这样传递 std::initializer_list<int> 的实例:

#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} {}
};

值得注意的是,在 C++14 及更高版本中,您可以只使用默认成员初始化程序:

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

此外,聚合初始化不生成构造函数。它完全绕过了它们。