![](/img/trans.png)
[英]how to use std::vector::emplace_back for vector<vector<int> >?
[英]emplace_back not working with std::vector<std::map<int, int>>
我试图将emplace_back
做成std::vector<std::map<int, int>>
,但找不到正确的语法来做到这一点。
#include<map>
#include<vector>
int main()
{
std::vector<std::map<int, int>> v;
std::map<int,int> a {{1,2}};
v.push_back({{1,2}});
v.emplace_back({1,2}); // error
v.emplace_back({{1,2}}); // error
v.emplace_back(({1,2})); // error
}
push_back
在这里工作,但不是emplace_back
。 我怎样才能让emplace_back
工作?
emplace_back
确实将所有参数转发给成员类型的匹配构造函数。 现在, std::map
有一个初始化列表构造函数,但它需要一个std::pair<const Key, Value>
,即std::pair<const int, int>
。 push_back
不是模板,因此它只需要一种类型,从而执行转换。 也就是说,这里不会发生类型推断。
你需要明确声明你想拥有一个std::pair
; 以下应该有效:
#include<map>
#include<vector>
int main()
{
std::vector<std::map<int, int>> v;
v.emplace_back(std::initializer_list<std::pair<const int, int>>{
{1,2},{3,4},{5,6}});
return 0;
}
出于同样的原因,这不编译:
v.emplace_back({std::pair<const int,int>(1,2),
std::pair<const int,int>(3,4)});
这是因为,虽然括号括起的列表可能会产生初始化列表,但它不必。 它也可以是构造函数调用或类似的东西。 所以,写作
auto l = {std::pair<const int,int>(1,2),
std::pair<const int,int>(3,4)};
产生l
的初始化列表,但表达式本身可能以另一种方式使用:
std::pair<std::pair<const int, int>, std::pair<const int, int>> p =
{std::pair<const int,int>(1,2),
std::pair<const int,int>(3,4)}
整个东西有点乱。
基本上,如果你有一个大括号括号列表,它可能会产生一个初始化列表或调用匹配的构造函数。 在某些情况下,编译器无法确定需要哪些类型; emplace_back
就是其中之一(因为转发)。 在其他情况下,它确实有效,因为所有类型都在表达式中定义。 例如:
#include <vector>
#include <utility>
int main()
{
std::vector<std::pair<const int, int>> v =
{{1,2},{3,4},{5,6}};
return 0;
}
现在它不起作用的原因是不能推断出任何类型。 即emplace_back
尝试推断输入类型的名称,但这是不可能的,因为大括号括号列表有几种类型可以描述。 因此,没有匹配的函数调用。
可以使用辅助函数实现如下:
#include <map>
#include <vector>
void emplace_work_around(
std::vector<std::map<int, int>>& v,
std::initializer_list<std::pair<const int,int>> && item
)
{
v.emplace_back(std::forward<std::initializer_list<std::pair<const int,int>>>(item));
}
int main()
{
std::vector<std::map<int, int>> v;
emplace_work_around(v,{{1,2}});
}
问题出在我们写的时候:
v.emplace_back({{1,2}}); // here {{1,2}} does not have a type.
编译器无法推断出参数的类型,也无法决定调用哪个构造函数。
根本的想法是,当你写一个像这样的函数
template<typename T>
void f(T) {}
并使用它
f( {1,2,3,4} ); //error
你会得到编译器错误,因为{1,2,3,4}确实有类型。
但是如果你将你的功能定义为
template<typename T>
void f(std::initializer_list<T>) {}
f( {1,2,3,4} );
然后它完美地编译。
如果我理解这些问题报告的话,这似乎目前不受支持:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.