Last active
January 14, 2023 17:12
-
-
Save mattbierner/6145671 to your computer and use it in GitHub Desktop.
C++ std::tuple map, foldl, and foldr
This file contains 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
/*------------------------------------------------------------------------------ | |
Common list operations (map, foldl, foldr) for C++ tuples. | |
Depends on Cons, Car, and Cdr for tuples from: https://gist.github.com/mattbierner/6145505 | |
------------------------------------------------------------------------------*/ | |
#include "tuple_ops.h" | |
/* Impl --------------------- */ | |
template<typename T, typename F> | |
struct MapImpl | |
{ | |
static auto Map(const T& t, const F& f) -> decltype(Cons(f(Car(t)), MapImpl<decltype(Cdr(t)), F>::Map(Cdr(t), f))) | |
{ | |
return Cons(f(Car(t)), MapImpl<decltype(Cdr(t)), F>::Map(Cdr(t), f)); | |
} | |
}; | |
template<typename F> | |
struct MapImpl<std::tuple<>, F> | |
{ | |
static std::tuple<> Map(const std::tuple<>&, const F&) { return std::make_tuple(); } | |
}; | |
template<typename T, typename F, typename Z> | |
struct FoldlImpl | |
{ | |
static auto Foldl(const T& t, const F& f, Z z) -> | |
decltype(FoldlImpl<decltype(Cdr(t)), F, decltype(f(Car(t), z))>::Foldl(Cdr(t), f, f(Car(t), z))) | |
{ | |
return FoldlImpl<decltype(Cdr(t)), F, decltype(f(Car(t), z))>::Foldl(Cdr(t), f, f(Car(t), z)); | |
} | |
}; | |
template<typename F, typename Z> | |
struct FoldlImpl<std::tuple<>, F, Z> | |
{ | |
static Z Foldl(const std::tuple<>&, const F&, Z z) { return z; } | |
}; | |
template<typename T, typename F, typename Z> | |
struct FoldrImpl | |
{ | |
static auto Foldr(const T& t, const F& f, Z z) -> | |
decltype(f(Car(t), FoldrImpl<decltype(Cdr(t)), F, Z>::Foldr(Cdr(t), f, z))) | |
{ | |
return f(Car(t), FoldrImpl<decltype(Cdr(t)), F, Z>::Foldr(Cdr(t), f, z)); | |
} | |
}; | |
template<typename F, typename Z> | |
struct FoldrImpl<std::tuple<>, F, Z> | |
{ | |
static Z Foldr(const std::tuple<>&, const F& f, Z z) { return z; } | |
}; | |
/* API --------------------- */ | |
/** | |
* Create a new tuple from the result of applying `f` to every value in `t`. | |
*/ | |
template<typename T, typename F> | |
auto Map(const T& t, const F& f) -> decltype(MapImpl<T, F>::Map(t, f)) | |
{ | |
return MapImpl<T, F>::Map(t, f); | |
} | |
/** | |
* Perform a left fold on tuple `t` with functor `f` and initial value `z`. | |
*/ | |
template<typename T, typename F, typename Z> | |
auto Foldl(const T& t, const F& f, Z z) -> decltype(FoldlImpl<T, F, Z>::Foldl(t, f, z)) | |
{ | |
return FoldlImpl<T, F, Z>::Foldl(t, f, z); | |
} | |
/** | |
* Perform a right fold on tuple `t` with functor `f` and initial value `z`. | |
*/ | |
template<typename T, typename F, typename Z> | |
auto Foldr(const T& t, const F& f, Z z) -> decltype(FoldrImpl<T, F, Z>::Foldr(t, f, z)) | |
{ | |
return FoldrImpl<T, F, Z>::Foldr(t, f, z); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment