Ответ 1
[Это полная переписывание. Мой предыдущий ответ не имел никакого отношения к проблеме.]
map
имеет две релевантные перегрузки insert
:
-
insert(const value_type& value)
и -
<template typename P> insert(P&& value)
.
Когда вы используете простой list-initializer map.insert({1, non_copyable()});
, учитываются все возможные перегрузки. Но найден только первый (тот, который принимает const value_type&
), так как другой не имеет смысла (нет способа догадаться, что вы хотели создать пару). Первая чрезмерная загрузка не работает, так как ваш элемент не копируется.
Вы можете сделать вторую работу по перегрузке, создав пару явно либо с помощью make_pair
, как вы уже описали, либо путем явного указания типа значения:
typedef std::map<int, non_copyable> map_type;
map_type m;
m.insert(map_type::value_type({1, non_copyable()}));
Теперь инициализатор списка знает, что искать конструкторы map_type::value_type
, находит соответствующий mova & shy; ble one, а результат представляет собой пару rvalue, которая привязывается к P&&
-перегрузке функции insert
.
(Другой вариант - использовать emplace()
с piecewise_construct
и forward_as_tuple
, хотя это будет намного более подробным.)
Я полагаю, что мораль здесь состоит в том, что инициализаторы списка ищут жизнеспособные перегрузки – но они должны знать, что искать!