2015-10-19 3 views
24

Я пытаюсь сделать emplace_back в 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?

+0

Их нет. используя только скобки и скобки – gjha

+0

Я считаю, что мы не передаем построенные объекты emplace_back. – gjha

+0

Существует 'v.emplace_back (std :: map {{1,2}});' .. не идеальный конечно –

ответ

7

можно добиться того, с помощью вспомогательной функции следующим образом:

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

затем компилирует прекрасно.

12

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 пытается вывести имя входных типов, но это невозможно, поскольку список, заключенный в фигурные скобки, имеет несколько типов, которые он может описать. Следовательно, не существует соответствующего вызова функции.

+0

Не совсем, это на самом деле имеет смысл. Это только немного сложно с пересылкой, но вы всегда можете написать стандартное предложение, чтобы исправить эту проблему. Это было бы намного более продуктивно ... –

+0

Вы, очевидно, не понимаете тип-систему C++. Может быть решение проблемы, что скобки-заключенные-списки не могут привязываться к параметру templated function (что опять же: имеет смысл, потому что это не тип), но кто-то должен будет его написать. Проблема в том, что в C++ разрешение типа должно возникать во время компиляции, и поэтому оно не работает. Это не глупо, потому что это выбор дизайна, чтобы сделать язык быстрым. –

+0

lol right okay Я не понимаю систему типов C++. Общепринято ли вам принимать чье-то мнение о «экспрессивности» языка и превращать его в прогорклое, совершенно неосведомленное избиение понимания человеком того, как язык технически построен? Как грустно для вас. Я предлагаю взглянуть на мой профиль, прежде чем продолжить небольшое путешествие по полосе ненависти. –

Смежные вопросы