Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CPlusPlusNotesForProfessionals.pdf
Скачиваний:
47
Добавлен:
20.05.2023
Размер:
5.11 Mб
Скачать

Chapter 110: Fold Expressions

Section 110.1: Unary Folds

Unary folds are used to fold parameter packs over a specific operator. There are 2 kinds of unary folds:

Unary Left Fold (... op pack) which expands as follows:

((Pack1 op Pack2) op ...) op PackN

Unary Right Fold (pack op ...) which expands as follows:

Pack1 op (... (Pack(N-1) op PackN))

Here is an example

template<typename... Ts> int sum(Ts... args)

{

return (... + args); //Unary left fold //return (args + ...); //Unary right fold

//The two are equivalent if the operator is associative.

//For +, ((1+2)+3) (left fold) == (1+(2+3)) (right fold)

//For -, ((1-2)-3) (left fold) != (1-(2-3)) (right fold)

}

int result = sum(1, 2, 3); // 6

Section 110.2: Binary Folds

Binary folds are basically unary folds, with an extra argument.

There are 2 kinds of binary folds:

Binary Left Fold - (value op ... op pack) - Expands as follows:

(((Value op Pack1) op Pack2) op ...) op PackN

Binary Right Fold (pack op ... op value) - Expands as follows:

Pack1 op (... op (Pack(N-1) op (PackN op Value)))

Here is an example:

template<typename... Ts>

int removeFrom(int num, Ts... args)

{

return (num - ... - args); //Binary left fold

//Note that a binary right fold cannot be used

//due to the lack of associativity of operator-

}

GoalKicker.com – C++ Notes for Professionals

559

int result = removeFrom(1000, 5, 10, 15); //'result' is 1000 - 5 - 10 - 15 = 970

Section 110.3: Folding over a comma

It is a common operation to need to perform a particular function over each element in a parameter pack. With C++11, the best we can do is:

template <class... Ts>

void print_all(std::ostream& os, Ts const&... args) { using expander = int[];

(void)expander{0,

(void(os << args), 0)...

};

}

But with a fold expression, the above simplifies nicely to:

template <class... Ts>

void print_all(std::ostream& os, Ts const&... args) { (void(os << args), ...);

}

No cryptic boilerplate required.

GoalKicker.com – C++ Notes for Professionals

560