Last active
January 14, 2023 17:12
-
-
Save mattbierner/6145505 to your computer and use it in GitHub Desktop.
C++ std::tuple cdr, car, cons
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
#include "tuple_ops.h" | |
template<typename T> | |
void print_tuple(const T& x) | |
{ | |
std::cout << "Head:" << Car(x) << " Remaining:" << std::tuple_size<T>::value - 1 << std::endl; | |
} | |
int main(int argc, const char* argv[]) | |
{ | |
auto list = Cons(6, Cons(std::string("hello world!"), Cons(5.53f, empty))); | |
auto list2 = Cons(322, Cons(list, Cons("abc", empty))); | |
print_tuple(list); // size=3, head=6 | |
print_tuple(Cdr(list)); // size=2, head="hello world!", | |
print_tuple(Cdr(Cdr(list))); // size=1, head=5.53f | |
auto x = Cdr(Cdr(Cdr(list))); // empty tuple. | |
std::cout << std::tuple_size<decltype(x)>::value << std::endl; | |
print_tuple(list2); // size=3, head=322 | |
Cdr(list2); // size=2, head=list, | |
print_tuple(Car(Cdr(list2))); // size=3, head=6, | |
print_tuple(Cdr(Car(Cdr(list2)))); // size=2, head="hello world!", | |
print_tuple(Cdr(Cdr(list2))); // size=1, head="abc", | |
} |
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
/*------------------------------------------------------------------------------ | |
Function list operations for std::tuple. | |
Operations are performed on tuple values. Unless noted, these operations | |
result in regular flat tuples and not recursive data structures. | |
------------------------------------------------------------------------------*/ | |
/* Implementation --------------------- */ | |
template<std::size_t... XS> | |
struct Seq | |
{ | |
template<std::size_t X> | |
using cons = Seq<X, XS...>; | |
}; | |
template<std::size_t start, std::size_t end> | |
struct Range | |
{ | |
static_assert(start < end, "Range: start > end"); | |
typedef | |
typename Range<start + 1, end>::type::template cons<start> | |
type; | |
}; | |
template<std::size_t start> | |
struct Range<start, start> | |
{ | |
typedef Seq<> type; | |
}; | |
template<typename T, std::size_t... N> | |
std::tuple<typename std::tuple_element<N, T>::type...> Select(const T& t, Seq<N...>) | |
{ | |
return std::make_tuple(std::get<N>(t)...); | |
} | |
/* API --------------------- */ | |
/** | |
* Empty list. | |
*/ | |
constexpr const std::tuple<> empty; | |
/** | |
* Get the first element of a tuple. | |
* | |
* Not valid for empty tuples. | |
*/ | |
template<typename T> | |
typename std::tuple_element<0, T>::type Car(const T& t) | |
{ | |
return std::get<0>(t); | |
} | |
/** | |
* Get a new tuple consisting of the rest of the tuple besides the first element. | |
* | |
* Not valid for empty tuples. | |
*/ | |
template<typename T, | |
typename R = typename Range<1, std::tuple_size<T>::value>::type> | |
auto Cdr(const T& t) -> decltype(Select(t, R())) | |
{ | |
return Select(t, R()); | |
} | |
/** | |
* Create a new tuple from a head value and existing tuple. | |
*/ | |
template<typename X, typename... XS> | |
std::tuple<X, XS...> Cons(X x, const std::tuple<XS...>& t) | |
{ | |
return std::tuple_cat(std::make_tuple(x), t); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment