emplace_back不适用于 std::vector<std::map<int, 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} );
那么它可以完美地编译
如果我对这些问题报告理解正确的话,这似乎是目前不支持的:
http://cplusplus.github.io/LWG/lwg-active.html # 2089
http://cplusplus.github.io/LWG/lwg-active.html 2070
- 'max'匹配'std::function<const int &(const int &, const int &)>'无过载
- 将 int 数组转换为 std::vector<int*>
- <Windows>为什么 std::thread::native_handle 返回类型为"long long unsigned int"的值,而不是 void*(又名 HANDLE)?
- 使用 std::vector::reverse_iterator 将 int 序列化为字节向量?
- 在 std::无符号字符的向量处存储 int 的十六进制表示形式
- '[](std::list& list)<int>{return std::move(list)}(list)' 是否保证将 'list' 留空?
- 从 std::vector<无符号字符>切片中提取 int?
- std::cout输出int时出现编译错误
- 如何创建一个类,以便向量工作 std::vector<MyClass<int>> v{ 1,2,3 };
- 对的排序向量 (std::vector<pair<int, int>>) 按对的第一个元素搜索并更新第二个元素值
- 如何使用 uint64_t 键类型从 std::map<int, std::string> 返回值?
- 为什么"weak.lock()"返回"nullptr" "auto weak=std::make_shared<int>(42);"的定义?
- 在标准中,模板参数的语法在哪里定义,例如,'std::function<int(char)>'?
- 如何以滑动窗口方式从 std::bitset 读取位并将它们转换为 int?
- 运算符 += 应用于 std::valarray<int*>
- C++ - 最坏情况和平均情况插入时间复杂度在 std::unordered_map <int,int>?
- 类型为 'std::map< char,int > 的 <Swig 对象的代理
- z3 提取 Seq Int 作为 std::vector<int>
- 我想知道为什么"std::unique_ptr<int> foo(新 int)"是合法的,因为"std::<int>unique_ptr"要求输入参数类型应该是"int"?
- std::int 和 struct 内存不足的映射 (std::Bad_alloc) c++