I can imagine a straightforward efficient implementation of fold expression expansion when all types of parameter pack are the same (simplified c++11 example):
#include <type_traits>
#include <array>
template <bool...>
struct bool_pack { };
template <bool... Bs>
using and_ = std::is_same<bool_pack<true, Bs...>, bool_pack<Bs..., true>>;
template <std::size_t I, std::size_t N, class T>
constexpr typename std::enable_if<(I == N - 1),T>::type fold_impl_impl(std::array<T, N> const &arr) {
return arr[I];
}
template <std::size_t I, std::size_t N, class T>
constexpr typename std::enable_if<(I < N - 1),T>::type fold_impl_impl(std::array<T, N> const &arr) {
return arr[I] + fold_impl_impl<I+1, N>(arr);
}
template <class T, std::size_t N>
constexpr T fold_impl(std::array<T, N> arr) {
return fold_impl_impl<0, N>(arr);
}
template <class T, class... Ts>
constexpr typename std::enable_if<and_<std::is_same<T, Ts>::value...>::value, T>::type fold(T first, Ts... rest) {
return fold_impl<T, sizeof...(Ts) + 1>({{first, rest...}});
}
int main() {
static_assert(fold(1, 2, 3, 4) == 10, "!");
}
Of course when we consider more general case, that is, when we can't really assume that the types are the same, we could replace reference to the std::array
with reference to the std::tuple
of parameter types. In this case however the tuple itself would most probably cause the complexity of the expansion to grow with a logarithm of parameter number.
IT would be possible to make the fold expressions to be treated intrinsically by the compiler to be sure the complexity of expansion is O(N)
, but in c++ standard draft in section [expr.prim.fold] I can't see guarantees on this.
Can we assume expansion of parameter pack using fold expression is cheap?