Skip to content

Fold expression

cppreference fold expression(since C++17)

NOTE: 这是C++17中增强parameter pack的新特性。

它使用的是functional programming中的reduce: 对一个sequence执行一个函数;需要注意的是,这是在compile time执行的,即它是compile time function execution,显然它是C++ 对 compile time computation的增强,参见C-and-C++\Compile-time-and-run-time\Compile-time-function-execution章节。

Reduces (folds) a parameter pack over a binary operator.

Example: all

template<typename ... Args>
bool all(Args ... args)
{
    return (... && args);
}
int main()
{
     // within all(), the unary left fold expands as
     //  return ((true && true) && true) && false;
     // b is false
    bool b = all(true, true, true, false);

}
// g++ --std=c++17

Example: endianness swap

#include <cstddef> // std::size_t
#include <type_traits>
#include <utility>

// compile-time endianness swap based on http://stackoverflow.com/a/36937049
template<class T, std::size_t ... N>
constexpr T bswap_impl(T i, std::index_sequence<N...>)
{
    return (((i >> N*CHAR_BIT & std::uint8_t(-1)) << (sizeof(T)-1-N)*CHAR_BIT) | ...);
}
template<class T, class U = std::make_unsigned_t<T>>
constexpr U bswap(T i)
{
    return bswap_impl<U>(i, std::make_index_sequence<sizeof(T)> { });
}

int main()
{
    static_assert(bswap<std::uint16_t>(0x1234u)==0x3412u);
    static_assert(bswap<std::uint64_t>(0x0123456789abcdefULL)==0xefcdab8967452301ULL);
}
// g++ --std=c++17 test.cpp

Example: push_back

#include <iostream>
#include <vector> // std::vector
#include <type_traits> // std::is_constructible_v
#include <utility> // std::forward

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

int main()
{
    std::vector<int> v;
    push_back_vec(v, 6, 2, 45, 12);
    push_back_vec(v, 1, 2, 9);
    for (int i : v)
        std::cout << i << ' ';
}
// g++ --std=c++17 test.cpp