我可以使用C++ 11大括号初始化语法来避免为简单聚合声明普通构造函数吗?

Vio*_*ffe 14 c++ initialization initializer-list c++11 list-initialization

假设我有以下代码:

#include <vector>

struct Foo
{
    int tag = 0;
    std::function<void ()> code;
};

int main()
{
   std::vector<Foo> v;
}
Run Code Online (Sandbox Code Playgroud)

现在我想要Foo使用特定的向量向量添加新项目,tagcode 不是明确创建临时项目.这意味着我必须添加一个构造函数Foo:

struct Foo
{
    inline Foo(int t, std::function<void ()> c): tag(t), code(c) {}

    int tag = 0;
    std::function<void ()> code;
};
Run Code Online (Sandbox Code Playgroud)

现在我可以使用emplace_back:

v.emplace_back(0, [](){});
Run Code Online (Sandbox Code Playgroud)

但是当我不得不再次这样做 - 第100次 - 使用新创建的结构时,我想:我不能使用大括号初始化器吗?像这样:

#include <vector>

struct Foo
{
   int tag = 0;
   std::function<void ()> code;
};

int main()
{
   std::vector<Foo> v;
   v.push_back(Foo{ 0, [](){} });
}
Run Code Online (Sandbox Code Playgroud)

这给了我一个编译错误(无法从'initializer-list'转换为'Foo'),但我希望这可以完成,我只是语法错了.

Ste*_*ppo 14

在C++ 11中,您不能将聚合初始值设定项与您一起使用,struct因为您对非静态成员使用了相同的初始值设定项tag.删除= 0部件,它将工作:

#include <vector>
#include <functional>

struct Foo
{
   int tag;
   std::function<void ()> code;
};

int main()
{
   std::vector<Foo> v;
   v.push_back(Foo{ 0, [](){} });
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意C++ 14中的这一变化,其中`Foo`是一个聚合,可以使用聚合初始化进行初始化. (2认同)

Pra*_*ian 9

根据C++ 11标准,Foo不是聚合,支持或等于初始化器的存在阻止它成为一个.

但是,对于C++ 14,此规则已更改,因此如果使用-std=c++14(或编译器的等效设置)编译代码,Foo将是聚合,并且代码将成功编译.

现场演示

对于C++ 11编译器,您必须删除初始化程序,它将生成Foo聚合,或者提供两个参数构造函数.