Почему вариационная функция не может использовать аргумент инициализации списка в С++ 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.

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


person abyss.7    schedule 15.06.2014    source источник


Ответы (2)


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

person Puppy    schedule 15.06.2014
comment
@Jeffrey: Нет, {...} не выражение. Первый — это специальный корпус для auto-вывода, которого на самом деле никогда не должно было быть (и, надеюсь, он будет удален когда-нибудь в будущем), а второй — просто конструкция из braced-init-list. - person Xeo; 15.06.2014
comment
@Massa: Да, этого было бы достаточно. - person Puppy; 15.06.2014

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

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

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

map.emplace(1, std::make_pair(1, 1));
person Ali    schedule 15.06.2014
comment
Причина не ясна - подскажите, какой initializer_list должен быть {1, "hi"}? - person Xeo; 15.06.2014
comment
@Xeo Я не понимаю твоего примера. auto x = { 1, "hi" }; также является ошибкой времени компиляции, так что же вы пытаетесь сделать? - person Ali; 15.06.2014
comment
@Xeo Я думаю, причина, если она есть, должна быть в чем-то другом. Я предполагаю, что разрешение такого вывода аргументов шаблона функции может иметь неприятные последствия. Хотя мне не удалось привести пример. - person Ali; 15.06.2014
comment
Проблема в том, что auto x = {1, 1}; вообще разрешено. Это особый случай в стандарте, и это ненужный хак, который следует удалить. :/ - person Xeo; 15.06.2014
comment
@Xeo Я думаю, что уже слишком поздно что-то менять, это сломает много кода. Но видите ли вы какой-нибудь крайний случай, в котором вывод initializer_list для аргумента шаблона функции может иметь неприятные последствия? - person Ali; 15.06.2014