emplace 和 unordered_map<?, std::array<?, N>>

Leo*_*adt 3 c++ dictionary unordered-map stdarray emplace

我有一个std::unordered_map<string, std::array<int, 2>>. emplace将值放入地图的语法是什么?

unordered_map<string, array<int, 2>> contig_sizes;
string key{"key"};
array<int, 2> value{1, 2};

// OK ---1
contig_sizes.emplace(key, value);

// OK --- 2
contig_sizes.emplace(key, std::array<int, 2>{1, 2});

// compile error --3
//contig_sizes.emplace(key, {{1,2}});

// OK --4 (Nathan Oliver)
// Very inefficient results in two!!! extra copy c'tor
contig_sizes.insert({key, {1,2}});

// OK --5
// One extra move c'tor followed by one extra copy c'tor
contig_sizes.insert({key, std::array<int, 2>{1,2}});

// OK --6 
// Two extra move constructors
contig_sizes.insert(pair<const string, array<int, 2>>{key, array<int, 2>{1, 2}});
Run Code Online (Sandbox Code Playgroud)

我正在使用clang++ -c -x c++ -std=c++14和叮当 3.6.0

我在http://ideone.com/pp72yR 中测试了代码

附录:(4) 由 Nathan Oliver 在下面的答案中提出

Nat*_*ica 5

cppreference std::unordered_map::emplace声明为

template< class... Args >
std::pair<iterator,bool> emplace( Args&&... args );
Run Code Online (Sandbox Code Playgroud)

所以它试图推断传递给它的类型。这将发挥作用 [temp.deduct.type] § 14.8.2.5

— 关联参数是初始化列表 (8.5.4) 但参数没有指定从初始化列表推导的类型 (14.8.2.1) 的函数参数。[ 例子:

template<class T> void g(T);  
g({1,2,3}); // error: no argument deduced for T
Run Code Online (Sandbox Code Playgroud)

—结束示例]

所以无法推导出任何类型。

如果要动态创建对象,则可以使用以下表单:

contig_sizes.emplace(key, std::array<int, 2>{1, 2});
Run Code Online (Sandbox Code Playgroud)

或者我们可以创建一个 typedef

typedef pair<const string, array<my_class, 2>> pair_type;
Run Code Online (Sandbox Code Playgroud)

然后我们可以有

contig_sizes.emplace(pair_type{key, {1, 2}});
Run Code Online (Sandbox Code Playgroud)

您还可以使用std::unordered_map::insertwhich 接受pair可以从花括号初始化列表构造的键/值。

contig_sizes.insert({key, {1, 2}});
Run Code Online (Sandbox Code Playgroud)