Created
June 4, 2018 23:03
-
-
Save AmatanHead/2c2a114350a86e09f1f56e4282d88d5b to your computer and use it in GitHub Desktop.
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 <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