Почему переменная функция не может "съесть" аргумент инициализации списка в С++ 11?

Пример кода:

#include <unordered_map>

int main() {
    std::unordered_map<int, std::pair<int, int>> map;

    map.emplace(1, {1, 1});

    return 0;
}

Где emplace() имеет подпись, например:

template <class... _Args>
pair<iterator, bool> emplace(_Args&&... __args);

gcc говорит, что функция ожидает 0 аргументов - 2. clang говорит, что функция ожидает 1 аргумент - 2.

Я даже не понимаю - в чем проблема с этим кодом?

Ответы

Ответ 1

Проблема заключается в том, что {1, 1} не является выражением и не имеет типа. Поскольку он не имеет типа, он не может быть выведен в список аргументов шаблона. Ни один из них не является правильным, потому что проблема не имеет ничего общего с количеством предоставленных аргументов.

Ответ 2

Я даже не понимаю - в чем проблема с этим кодом?

По какой-то неясной причине аргумент инициализатора-списка - это не выведенный контекст, см. initializer_list и вывод типа шаблона. Это объясняется тем, что в § 14.8.2.5/5 стандарта С++ 11 так сказано. Я не знаю обоснования этого, казалось бы, непоследовательного и противоречивого поведения, но мы не одиноки:

Что касается вашей ситуации, возможно, самое простое решение:

map.emplace(1, std::make_pair(1, 1));