C++ TutorialBasic input/output in c++C++ AlignmentC++ Argument Dependent Name LookupC++ Arithmitic MetaprogrammingC++ ArraysC++ Atomic TypesC++ AttributesC++ autoC++ Basic Type KeywordsC++ Bit fieldsC++ Bit ManipulationC++ Bit OperatorsC++ Build SystemsC++ C incompatibilitiesC++ C++11 Memory ModelC++ Callable ObjectsC++ Classes/StructuresC++ Client server examplesC++ Common compile/linker errors (GCC)C++ Compiling and BuildingC++ Concurrency with OpenMPC++ Const CorrectnessC++ const keywordC++ Constant class member functionsC++ constexprC++ ContainersC++ Copy ElisionC++ Copying vs AssignmentC++ Curiously Recurring Template Pattern (CRTP)C++ Date and time using chrono headerC++ Debugging and Debug-prevention Tools & TechniquesC++ decltypeC++ Digit separatorsC++ EnumerationC++ ExceptionsC++ Explicit type conversionsC++ Expression templatesC++ File I/OC++ Floating Point ArithmeticC++ Flow ControlC++ Fold ExpressionsC++ Friend keywordC++ function call by value vs. call by referenceC++ Function OverloadingC++ Function Template OverloadingC++ Futures and PromisesC++ Header FilesC++ Implementation-defined behaviorC++ Inline functionsC++ Inline variablesC++ IterationC++ IteratorsC++ KeywordsC++ LambdasC++ Layout of object typesC++ Linkage specificationsC++ LiteralsC++ LoopsC++ Memory managementC++ MetaprogrammingC++ Move SemanticsC++ mutable keywordC++ MutexesC++ NamespacesC++ Non-Static Member FunctionsC++ One Definition Rule (ODR)C++ Operator OverloadingC++ operator precedenceC++ OptimizationC++ Overload resolutionC++ Parameter packsC++ Perfect ForwardingC++ Pimpl IdiomC++ PointersC++ Pointers to membersC++ PolymorphismC++ PreprocessorC++ ProfilingC++ RAII: Resource Acquisition Is InitializationC++ Random number generationC++ Recursive MutexC++ Refactoring TechniquesC++ ReferencesC++ Regular expressionsC++ Resource ManagementC++ Return Type CovarianceC++ Returning several values from a functionC++ RTTI: Run-Time Type InformationC++ Scopes

C++ Fold Expressions

From WikiOD

Remarks[edit | edit source]

Fold Expressions are supported for the following operators

+ - * / % \ˆ & << >>
+= -= *= /= %= \ˆ= &= = <<= >>= =
== != < > <= >= && , .* ->*

When folding over an empty sequence, a fold expression is ill-formed, except for the following three operators:

Operator Value when parameter pack is empty
&& true
, void()

Unary Folds[edit | edit source]

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

Binary Folds[edit | edit source]

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-

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

Folding over a comma[edit | edit source]

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(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.