• тип-член type
remove_reference
будет иметь тип string
;• типом возвращаемого значения функции move()
string&&
;• у параметра t
move()
будет тип string&&
;Соответственно, этот вызов создает экземпляр move
string&& move(string &&t)
Тело этой функции возвращает тип static_cast
t
уже является string&&
, поэтому приведение не делает ничего. Следовательно, результатом этого вызова будет ссылка на r-значение, которое было дано.Теперь рассмотрим второе присвоение, которое вызывает функцию std::move(s1)
move()
является l-значение. Поэтому на сей раз:• выведенным типом Т
string&
(ссылка на тип string
, а не просто string
);• следовательно, экземпляр шаблона remove_reference
string&
;• тип-член type
remove_reference
будет иметь тип string
;• типом возвращаемого значения функции move()
string&&
;• параметр t
move()
будет создан как экземпляр string& &&
, который сворачивается в string&
.Таким образом, этот вызов создает экземпляр шаблона move
string&& move(string &t)
Тело этого экземпляра возвращает тип static_cast
t
является string&
, который приведение преобразует в тип string&&
.static_cast
static_cast
static_cast
, можно Привязка ссылки на r-значение к l-значению создает код, который работает с разрешением ссылке на r-значение заменять l-значение. Иногда, как в случае с функцией reallocate()
StrVec
(см. раздел 13.6.1), известно, что замена l-значения безопасна. И наконец, хотя такие приведения можно написать непосредственно, намного проще использовать библиотечную функцию move()
std::move()
существенно облегчает поиск в коде места, потенциально способного заменить l-значения.Упражнение 16.46
. Объясните, что делает этот цикл из функцииStrVec::reallocate()
(раздел 13.5):for (size_t i = 0; i != size(); ++i)
alloc.construct(dest++, std::move(*elem++));
Некоторые функции должны перенаправлять другим функциям один или несколько своих аргументов с
В качестве примера напишем функцию, получающую вызываемое выражение и два дополнительных аргумента. Функция вызовет предоставленное вызываемое выражение с другими двумя аргументами в обратном порядке. Вот первый фрагмент функции обращения:
//
//
//
//
template
void flip1(F f, T1 t1, T2 t2) {
f(t2, t1);
}
Этот шаблон работает прекрасно, пока он не используется для вызова функции со ссылочным параметром:
void f(int v1, int &v2) //
{
cout << v1 << " " << ++v2 << endl;
}
Здесь функция f()
v2
. Но если происходит вызов функции f()
через шаблон flip1
, внесенные функцией f()
изменения не затронут первоначальный аргумент:f(42, i); //
flip1(f, j, 42); //