Проблема связана с std::pair
конструкторами и разрешением вывода / перегрузки аргументов шаблона:
pair( const T1& x, const T2& y ); // (1)
template< class U1, class U2 >
pair( U1&& x, U2&& y ); // (2)
Обратите внимание, что есть, по крайней мере, один «отсутствующий» конструктор:
pair( T1&& x, T2&& y ); // (3)
Когда вы используете инициализацию списка для первого параметра, выбранный конструктор будет не (2)
(с U1 = std::initializer_list<int>
), а (1)
1 . Таким образом, вам нужно создать временную std::vector<int>
, которая передается как const
-ссылка на (1)
, которая должна сделать копию.
Эмпирически это можно подтвердить одним из следующих способов:
- создание собственного
pair
с третьим конструктором, упомянутым выше & mdash; в этом случае будет выбран (3)
, а временный vector
будет перемещен;
- явно создает
std::initializer_list<int>
при создании std::pair
:
pair<vector<int>, int>{ std::initializer_list<int>{1,2,3,4,5}, 1 };
С другой стороны std::optional
как конструктор с одним шаблоном:
template < class U = value_type >
constexpr optional( U&& value );
... но есть значение по умолчанию для U
, что делает этот конструктор допустимым кандидатом для разрешения перегрузки.
1 Когда вы звоните pair{ {1,2,3,4,5}, 1 }
, U1
находится в невыбранном контексте в пределах (2)
[temp.deduct.type] # 5.6 , поэтому вычет не выполняется, поэтому выбран (1)
.