2015-10-06 12 views
2

У меня есть std::unordered_map<string, std::array<int, 2>>. Каков синтаксис emplace значения на карте?emplace and unordered_map <?, std :: array <?, N>>

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}}); 

Я использую clang++ -c -x c++ -std=c++14 и лязг 3.6.0

Я тестировал код в http://ideone.com/pp72yR

Добавление: (4) предложил Натан Оливер в ответ ниже

+1

'emplace' должен выводить тип своих аргументов, но' {{1,2}} 'не имеет типа (это не выражение). – dyp

ответ

4

От cppreferencestd::unordered_map::emplace заявлен как

template< class... Args > 
std::pair<iterator,bool> emplace(Args&&... args); 

Поэтому он пытается вывести типы, переданные ему. Это привнесет в игру [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 

-end пример]

Так тип не может быть выведен.

Если вы хотите создавать объекты на лету, то вы должны использовать форму:

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

Или мы можем создать typedef

typedef pair<const string, array<my_class, 2>> pair_type; 

И тогда мы можем иметь

contig_sizes.emplace(pair_type{key, {1, 2}}); 

Вы также можете использовать std::unordered_map::insert, который принимает pair ключа/значения, которое может быть построено из скопированного списка инициализаторов.

contig_sizes.insert({key, {1, 2}}); 
+0

'unordered_map :: insert' приводит к добавлению двух дополнительных копий c'tors (http://ideone.com/pp72yR). Чтобы уменьшить его, чтобы перемещать только c'tors, вам, похоже, нужен этот ужасный синтаксис: 'contig_sizes.insert (пара > {key, array {1, 2}});' –

+1

@LeoGoodstadt That может быть решена с помощью простого 'typedef'. 'typedef pair > Пара_type;', а затем 'contig_sizes.insert (пара_type {key, {1, 2}});' – NathanOliver

+0

@LeoGoodstadt Я обновил ответ, чтобы показать легкое на глазах 'emplace () 'использование. – NathanOliver