// остальные члены, как в разделе 13.5

};

Схема && в развертывании пакета параметров шаблона означает, что каждый параметр функции будет ссылкой на r-значение на соответствующий ей аргумент.

Во-вторых, функцию forward() следует использовать для сохранения первоначальных типов аргументов, когда функция emplace_back() передает их функции construct() (см. раздел 16.2.7):

template

inline

void StrVec::emplace_back(Args&&... args) {

 chk_n_alloc(); // пересоздает StrVec при необходимости

 alloc.construct(first_free++, std::forward(args)...);

}

Тело функции emplace_back() вызывает функцию chk_n_alloc() (см. раздел 13.5), чтобы гарантировать наличие достаточного места для элемента, и вызывает функцию construct(), чтобы создать элемент в позиции, на которую указывает указатель first_free.

std::forward(args)...

Развертывание в вызове функции construct() разворачивает оба пакета: параметров шаблона Args и параметров функции args. Эта схема создает элементы в формате:

std::forward<Ti>(ti)

где Ti представляет тип i-го элемента в пакете параметров шаблона, a ti представляет i-й элемент в пакете параметров функции. Например, если svec имеет тип StrVec, то при вызове

svec.emplace_back(10, 'c'); // добавит cccccccccc как новый последний

                            // элемент

схема в вызове функции construct() развернется в

std::forward(10), std::forward(c)

Использование функции forward() в этом вызове гарантирует, что если функция emplace_back() будет вызвана с r-значением, то функция construct() также получит r-значение. Например, в вызове

svec.emplace_back(s1 + s2); // использует конструктор перемещения

аргумент функции emplace_back() является r-значением, которое передается функции construct() как

std::forward(string("the end"))

Типом результата вызова forward будет strings&, поэтому функция construct() будет вызвана со ссылкой на r-значение. Функция construct(), в свою очередь, перенаправит этот аргумент конструктору перемещения класса string, чтобы создать этот элемент.

Совет. Перенаправление и шаблоны с переменным количеством аргументов

Функции с переменным количеством аргументов зачастую перенаправляют свои параметры другим функциям. Форма таких функций, как правило, подобна функции emplace_back():

// у функции fun() может быть любое количество параметров, каждый

// из которых является ссылкой r-значения на тип параметра шаблона

template

void fun(Args&&... args) // развертывание Args в список ссылок

                         // на r-значения

{

 // аргумент work() развертывает как Args, так и args

 work(std::forward(args)...);

}

Здесь предполагается перенаправить все аргументы функции fun() другой функции, work(), которая, по-видимому, осуществляет реальную работу. Как и вызов функции construct() в функции emplace_back(), развертывание в вызове функции work() разворачивает и пакет параметров шаблона, и пакет параметров функции.

Поскольку параметры функции fun() являются ссылками на r-значение, функции fun() можно передать аргументы любого типа; поскольку для передачи этих аргументов используется функция std::forward(), вся информация о типах этих аргументов будет сохраняться в вызове функции work().

Упражнения раздела 16.4.3

Упражнение 16.58. Напишите функцию emplace_back() для собственного класса StrVec и для класса Vec, написанного в упражнении раздела 16.1.2.

Перейти на страницу:

Похожие книги