Last active
November 27, 2019 15:51
-
-
Save glukianets/a39e57c95e8a035c47c3d9a151ac5b68 to your computer and use it in GitHub Desktop.
Performs any kind of accumulating operation over any amount of variably nested arrays and tuples. Can be extended to support more types.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace impl { | |
template<typename T> | |
struct FlatTypeTraits; | |
template<typename T, size_t L> | |
struct FlatTypeTraits<std::array<T, L>> { | |
template<typename AccT, typename CallableT> | |
static constexpr void acc(const std::array<T, L> &array, AccT &acc, CallableT &&callable) { | |
for (const T &element : array) | |
FlatTypeTraits<T>::acc(element, acc, callable); | |
} | |
}; | |
template<typename T> | |
struct FlatTypeTraits { | |
template<typename AccT, typename CallableT> | |
static constexpr void acc(const T &value, AccT &acc, CallableT &&callable) { std::invoke(callable, acc, value); } | |
}; | |
template<typename ... T> | |
struct FlatTypeTraits<std::tuple<T...>> { | |
template<typename AccT, typename CallableT> | |
static constexpr auto acc(const std::tuple<T...> &tuple, AccT &acc, CallableT &&callable) { | |
accHelper(tuple, acc, callable); | |
} | |
template<size_t I = 0, typename AccT, typename CallableT, typename ...AT> | |
static constexpr auto accHelper(const std::tuple<AT...> &tuple, AccT &acc, CallableT &&callable) { | |
if constexpr (I < sizeof...(T)) { | |
FlatTypeTraits<std::tuple_element_t<I, std::tuple<AT...>>>::acc(std::get<I>(tuple), acc, callable); | |
accHelper<I + 1>(tuple, acc, callable); | |
} | |
} | |
}; | |
} // impl | |
template<typename T, typename AccT, typename CallableT> | |
auto flat_accumulate(T &&v, AccT acc, CallableT &&callable) -> AccT { | |
impl::FlatTypeTraits<std::remove_reference_t<T>>::acc(std::forward<T>(v), acc, callable); | |
return acc; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment