Skip to content

Instantly share code, notes, and snippets.

@mattbierner
Last active January 14, 2023 17:12
Show Gist options
  • Save mattbierner/6145505 to your computer and use it in GitHub Desktop.
Save mattbierner/6145505 to your computer and use it in GitHub Desktop.
C++ std::tuple cdr, car, cons
#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",
}
/*------------------------------------------------------------------------------
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