Skip to content

Instantly share code, notes, and snippets.

@AmatanHead
Created June 4, 2018 23:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AmatanHead/2c2a114350a86e09f1f56e4282d88d5b to your computer and use it in GitHub Desktop.
Save AmatanHead/2c2a114350a86e09f1f56e4282d88d5b to your computer and use it in GitHub Desktop.
//#include <library/unittest/registar.h>
#include <tuple>
#include <string>
#include <iostream>
template <typename T>
void print(const T& t);
template <typename... T>
void print(const std::tuple<T...>& t);
template<class Tuple, std::size_t N>
struct TuplePrinter {
static void print(const Tuple& t)
{
TuplePrinter<Tuple, N-1>::print(t);
std::cout << ", ";
::print(std::get<N-1>(t));
}
};
template<class Tuple>
struct TuplePrinter<Tuple, 1> {
static void print(const Tuple& t)
{
::print(std::get<0>(t));
}
};
template<class Tuple>
struct TuplePrinter<Tuple, 0> {
static void print(const Tuple&)
{
}
};
template <typename T>
void print(const T& t) {
std::cout << t;
}
template <typename... T>
void print(const std::tuple<T...>& t) {
std::cout << "(";
TuplePrinter<decltype(t), sizeof...(T)>::print(t);
std::cout << ")";
}
namespace NDetail {
template <typename T, typename TupleOfTuples, std::size_t... I>
inline constexpr auto PrependToTuplesImpl(T t, TupleOfTuples ts, std::index_sequence<I...>);
template <typename Tuple, std::size_t... I>
inline constexpr auto TupleCrossProductImpl(Tuple first, std::index_sequence<I...>);
template <typename Tuple, typename TupleOfTuples, std::size_t... I>
inline constexpr auto TupleCrossProductImpl(Tuple firstTuple, std::index_sequence<I...>, TupleOfTuples restTupleProduct);
template <typename T, typename TupleOfTuples>
inline constexpr auto PrependToTuples(T t, TupleOfTuples ts);
template <typename First>
inline constexpr auto TupleCrossProduct(First first);
template <typename First, typename... Rest>
inline constexpr auto TupleCrossProduct(First first, Rest... rest);
template <typename T, typename TupleOfTuples, std::size_t... I>
inline constexpr auto PrependToTuplesImpl(T t, TupleOfTuples ts, std::index_sequence<I...>) {
return std::make_tuple(std::tuple_cat(std::make_tuple(t), std::get<I>(ts))...);
};
template <typename Tuple, std::size_t... I>
inline constexpr auto TupleCrossProductImpl(Tuple first, std::index_sequence<I...>) {
return std::make_tuple(std::make_tuple(std::get<I>(first))...);
}
template <typename Tuple, typename TupleOfTuples, std::size_t... I>
inline constexpr auto TupleCrossProductImpl(Tuple firstTuple, std::index_sequence<I...>, TupleOfTuples restTupleProduct) {
return std::tuple_cat(PrependToTuples(std::get<I>(firstTuple), restTupleProduct)...);
}
/**
* Prepend the given element to all tuples in the given tuple.
*
* Let:
*
* @code
* auto t = make_tuple(make_tuple(a, b), make_tuple(c, d));
* @endcode
*
* Than:
*
* @code
* PrependToTuples(x, t) == make_tuple(make_tuple(x, a, b), make_tuple(x, c, d));
* @endcode
*/
template <typename T, typename TupleOfTuples>
inline constexpr auto PrependToTuples(T t, TupleOfTuples ts) {
return PrependToTuplesImpl(t, ts, std::make_index_sequence<std::tuple_size<TupleOfTuples>::value>());
};
/**
* Cross-product given tuples, returning a tuple of tuples.
*
* Let:
*
* @code
* auto t0 = make_tuple();
* auto t1 = make_tuple(a);
* auto t2 = make_tuple(b, c);
* @endcode
*
* Than:
*
* @code
* TupleCrossProduct(t0) == make_tuple();
* TupleCrossProduct(t0, t2) == make_tuple();
* TupleCrossProduct(t1, t2) == make_tuple(make_tuple(a, b), make_tuple(a, c));
* TupleCrossProduct(t2, t2) == make_tuple(make_tuple(b, b), make_tuple(b, c), make_tuple(c, b), make_tuple(c, c));
* @endcode
*/
/// @{
inline constexpr std::tuple<> TupleCrossProduct() {
return {};
}
template <typename First>
inline constexpr auto TupleCrossProduct(First first) {
auto indices = std::make_index_sequence<std::tuple_size<First>::value>();
return TupleCrossProductImpl(first, indices);
}
template <typename First, typename... Rest>
inline constexpr auto TupleCrossProduct(First first, Rest... rest) {
auto indices = std::make_index_sequence<std::tuple_size<First>::value>();
return TupleCrossProductImpl(first, indices, TupleCrossProduct(rest...));
}
/// @}
}
static constexpr const auto p1 = std::make_tuple(10, "str");
static constexpr const auto p2 = std::make_tuple("xxx", 0);
static const auto p3 = std::make_tuple(15.0, "foo", "std::string()");
int main() {
{
const auto t = NDetail::TupleCrossProduct();
std::cout << std::tuple_size<decltype(t)>::value;
}
{
const auto t = NDetail::TupleCrossProduct(p1);
std::cout << std::tuple_size<decltype(t)>::value;
}
{
const auto t = NDetail::TupleCrossProduct(p1, p2);
std::cout << std::tuple_size<decltype(t)>::value;
}
{
const auto t = NDetail::TupleCrossProduct(p1, p2, p3);
std::cout << std::tuple_size<decltype(t)>::value;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment