Fold expressions

Fold expressions

With C++11 we got variadic templates which is a great feature, especially if you want to work with a variable number of input parameters to a function. For example, previously (pre C++11) you had to write several different versions of a function (like one for one parameter, another for two parameters, another for three params… ).

Still, variadic templates required some additional code when you wanted to implement ‘recursive’ functions like sum, all. You had to specify rules for the recursion:

For example:

auto SumCpp11(){
    return 0;
}

template<typename T1, typename... T>
auto SumCpp11(T1 s, T... ts){
    return s + SumCpp11(ts...);
}

And with C++17 we can write much simpler code:

template<typename ...Args> auto sum(Args ...args) 
{ 
    return (args + ... + 0); 
}

// or even:

template<typename ...Args> auto sum2(Args ...args) 
{ 
    return (args + ...);
}

Simple folds

#include <iostream>
#include <string>
using namespace std;

template<typename ...Args> auto sum(Args ...args) 
{ 
    return (args + ... + 0); 
}
template<typename ...Args> auto sum2(Args ...args) 
{ 
    return (args + ...);
}
int main()
{
    cout << sum(1, 2, 3, 4, 5, 6, 7) << "\n";
    cout << sum2(1, 2, 3, 4, 5, 6, 7) << "\n";
}

Run
Fold expressions over a parameter pack.

EXPRESSION EXPANSION
(… op pack) ((pack1 op pack2) op …) op packN
(init op … op pack) (((init op pack1) op pack2) op …) op packN
(pack op …) pack1 op (… op (packN-1 op packN))
(pack op … op init) pack1 op (… op (packN-1 op (packN op init)))

Also by default we get the following values for empty parameter packs:

OPERATOR DEFAULT VALUE
&& true
|| false
, void()
Here’s quite nice implementation of a printf using folds P0036R0:

template<typename ...Args>
void FoldPrint(Args&&... args) {
    (cout << ... << forward<Args>(args)) << '\n';
}

Print and folds

#include <iostream>
#include <string>
using namespace std;

template<typename ...Args>
void FoldPrint(Args&&... args) {
    (cout <<  ... <<  forward<Args>(args)) << '\n';
}
int main()
{
    FoldPrint("hello", ", ", 10, ", ", 90.0);
}
Success!
Standard Output
hello, 10, 90

Or a fold over a comma operator:

template<typename T, typename... Args>
void push_back_vec(std::vector<T>& v, Args&&... args)
{
    (v.push_back(args), ...);
}

Push back and folds

#include <iostream>
#include <string>
#include <vector>
using namespace std;

template<typename T, typename... Args>
void FoldPushBack(vector<T>& v, Args&&... args)
{
    (v.push_back(args), ...);
}
int main()
{
    vector<int> v;
    FoldPushBack(v, 1, 2, 3, 4);

    for (auto &i : v)
        cout << i << "\n";
}

Run
In general, fold expression allows writing cleaner, shorter and probably easier to read code.

More details in:

  • N4295 and P0036R0 “Using fold expressions to simplify variadic
    function templates” in Modern C++ Programming Cookbook.
  • Simon Brand: Exploding tuples with fold expressions
  • Baptiste Wicht: C++17 Fold Expressions
  • Fold Expressions - ModernesCpp.com
  • MSVC not yet, GCC: 6.0, Clang: 3.6 (N4295)/3.9(P0036R0).
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值