//
};
Схема &&
в развертывании пакета параметров шаблона означает, что каждый параметр функции будет ссылкой на r-значение на соответствующий ей аргумент.
Во-вторых, функцию forward()
следует использовать для сохранения первоначальных типов аргументов, когда функция emplace_back()
передает их функции construct()
(см. раздел 16.2.7):
template
inline
void StrVec::emplace_back(Args&&... args) {
chk_n_alloc(); //
alloc.construct(first_free++, std::forward
}
Тело функции emplace_back()
вызывает функцию chk_n_alloc()
(см. раздел 13.5), чтобы гарантировать наличие достаточного места для элемента, и вызывает функцию construct()
, чтобы создать элемент в позиции, на которую указывает указатель first_free
.
std::forward
Развертывание в вызове функции construct()
разворачивает оба пакета: параметров шаблона Args
и параметров функции args
. Эта схема создает элементы в формате:
std::forward<
где
представляет тип
-го элемента в пакете параметров шаблона, a
представляет
-й элемент в пакете параметров функции. Например, если svec
имеет тип StrVec
, то при вызове
svec.emplace_back(10, 'c'); //
//
схема в вызове функции construct()
развернется в
std::forward
Использование функции forward()
в этом вызове гарантирует, что если функция emplace_back()
будет вызвана с r-значением, то функция construct()
также получит r-значение. Например, в вызове
svec.emplace_back(s1 + s2); //
аргумент функции emplace_back()
является r-значением, которое передается функции construct()
как
std::forward
Типом результата вызова forward
будет strings&
, поэтому функция construct()
будет вызвана со ссылкой на r-значение. Функция construct()
, в свою очередь, перенаправит этот аргумент конструктору перемещения класса string
, чтобы создать этот элемент.
Функции с переменным количеством аргументов зачастую перенаправляют свои параметры другим функциям. Форма таких функций, как правило, подобна функции emplace_back()
:
//
//
template
void fun(Args&&... args) //
//
{
//
work(std::forward
}
Здесь предполагается перенаправить все аргументы функции fun()
другой функции, work()
, которая, по-видимому, осуществляет реальную работу. Как и вызов функции construct()
в функции emplace_back()
, развертывание в вызове функции work()
разворачивает и пакет параметров шаблона, и пакет параметров функции.
Поскольку параметры функции fun()
являются ссылками на r-значение, функции fun()
можно передать аргументы любого типа; поскольку для передачи этих аргументов используется функция std::forward()
, вся информация о типах этих аргументов будет сохраняться в вызове функции work()
.
Упражнение 16.58. Напишите функцию emplace_back()
для собственного класса StrVec
и для класса Vec
, написанного в упражнении раздела 16.1.2.