Как передаётся brace-init-list в std::vector::push_back?
У меня есть std::vector<std::string>.
Если я в него делаю push_back({ '1', '2' }), то всё ок.
Но если сделать в него emplace_back(std::move({ '1', '2' })), то код не скомпилируется, хотя, судя по реализации push_back, он делает буквально то же самое.
_CONSTEXPR20 void push_back(_Ty&& _Val) {
// insert by moving into element at end, provide strong guarantee
emplace_back(_STD move(_Val));
}
Каких нюансов я не понимаю? И каким образом brace-init-list доходит до конструктора строки в векторе при использовании push_back? Ведь brace-init-list не является объектом, как на него можно rvalue reference делать?
Ответы (1 шт):
Чтобы std::move({'1', '2'}) сработал, компилятору нужно угадать шаблонный параметр move (тип параметра функции) из типа {'1', '2'}. А у фигурных скобок нет типа1 - поэтому здесь ошибка.
Зато в push_back(_Ty &&) тип параметра известен заранее (из шаблонного параметра вектора), поэтому при вызове из фигурных скобок создается временный объект этого типа.
brace-init-list не является объектом, как на него можно rvalue reference делать?
Ссылка не на него, а на временный объект, который из него создается.
1 Нет, тип не std::initializer_list<char>. Это заметнее на вот таком примере:
struct A {int x; std::string y;};
std::vector<A> a;
a.push_back({1, "2"}); // Явно не `initializer_list<??>`.