如何初始化结构内部的对向量?

时间:2019-07-06 13:08:58

标签: c++

我需要在以下代码中向矢量“项目”中手动添加项目,但出现错误“ emplace_back':函数未使用5个参数”-如何使它工作?

    enum class ITM {
        ...
    };

    enum class RES {
        res1,
        res2
    };

    typedef std::vector<std::pair<RES,int>> ingredient_list;

    struct _item {
        ITM name;
        double buy, sell, craft;
        ingredient_list ingr;
    };

    std::vector<_item> items;

    items.emplace_back(ITM::lm54, 0, 0, 0, { {RES::res1, 50}, {RES::res2, 70} });

4 个答案:

答案 0 :(得分:1)

类型_item没有带有五个参数的构造函数,但是可以使用move构造函数。

items.emplace_back(_item{ ..., ..., ..., ..., ... });

emplace_back()试图找到_item的构造函数,该构造函数接受相同的参数,以便在调用此构造函数的过程中转发
move构造函数隐式存在(除非明确禁用或被某些数据成员禁用),因此提供临时_item作为emplace_back()的参数可以很好地将其转发到将使用的move构造函数用于在向量内部进行就地构建。

答案 1 :(得分:1)

您可以这样做:

std::vector<_item> items{
    { ITM::Foo, 1., 2., 3., { { RES::res1, 1 } } },
    { ITM::Bar, 4., 5., 6., { { RES::res1, 2 }, { RES::res2, 3 } } }
};

答案 2 :(得分:1)

您的代码为什么不起作用?因为两件事。

emplace_back会扣除参数,并且您已经传递了初始化列表({}前面没有任何类型)。初始化程序列表在模板推导上不能很好地工作(实际上,它们根本不起作用,例如:

template <typename F> void foo(F &&f)
{
    std::vector<int> q = f;
}        
int main()
{
    foo({ 1 });
}

产生可怕的东西

prog.cpp: In function ‘int main()’:
prog.cpp:12:11: error: no matching function for call to ‘foo(<brace-enclosed initializer list>)’
  foo({ 1 });
           ^
prog.cpp:5:28: note: candidate: template<class F> void foo(F&&)
 template <typename F> void foo(F &&f)
                            ^~~
prog.cpp:5:28: note:   template argument deduction/substitution failed:
prog.cpp:12:11: note:   couldn't deduce template parameter ‘F’
  foo({ 1 });
           ^

要对此进行修改,您需要添加类型:

items.emplace_back(ITM::lm54, 0, 0, 0, ingredient_list{ {RES::res1, 50}, {RES::res2, 70} });

第二,这是您的items_类型是POD(纯旧数据-没有构造函数,没有其他东西)。编译器允许您使用构造函数语法(_item(values)来初始化POD类型,但这不能与vector(和其他容器)一起使用,因为它们在这样的内部使用:

::new((void *)__p) _Up(std::forward<_Args>(__args)...);

忽略POD事物。因此,您要么需要在类型名前面加上参数(从而创建对象并强制编译器使用move构造函数),要么在类中定义构造函数(从而避免出现整个POD问题)。

答案 3 :(得分:1)

您的代码无法正常工作,因为您需要_item的构造函数,该构造函数需要使用所有5个参数,并且看来您没有一个。

幸运的是,从C ++ 11开始,您可以使用list_initialization

items.push_back({ITM::lm54, 0, 0, 0, { {RES::res1, 50}, {RES::res2, 70} }});

您只需将初始化项所需的信息放在花括号之间即可。这应该创建一个_item对象,然后将其推入容器。