Skip to content

Instantly share code, notes, and snippets.

@westfly
Forked from talybin/to_tuple.cpp
Created February 5, 2021 13:50
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 westfly/a3235014fa1e2a98abeb3c0e44ae1ccf to your computer and use it in GitHub Desktop.
Save westfly/a3235014fa1e2a98abeb3c0e44ae1ccf to your computer and use it in GitHub Desktop.
Struct to tuple conversion (CppCon 2019, Kris Jusiak)
#include <tuple>
#include <type_traits>
template <class T, class... TArgs>
decltype(void(T{std::declval<TArgs>()...}), std::true_type{})
test_is_braces_constructible(int);
template <class, class...>
std::false_type
test_is_braces_constructible(...);
template <class T, class... TArgs>
using is_braces_constructible = decltype(test_is_braces_constructible<T, TArgs...>(0));
struct any_type
{
template <class T>
constexpr operator T(); // non explicit
};
template <class T>
constexpr auto to_tuple(T&& object) noexcept
{
using type = std::decay_t<T>;
if constexpr(is_braces_constructible<type, any_type, any_type, any_type, any_type, any_type, any_type, any_type, any_type, any_type, any_type>{})
{
auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10] = std::forward<T>(object);
return std::tuple(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
} else if constexpr(is_braces_constructible<type, any_type, any_type, any_type, any_type, any_type, any_type, any_type, any_type, any_type>{})
{
auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9] = std::forward<T>(object);
return std::tuple(p1, p2, p3, p4, p5, p6, p7, p8, p9);
} else if constexpr(is_braces_constructible<type, any_type, any_type, any_type, any_type, any_type, any_type, any_type, any_type>{})
{
auto&& [p1, p2, p3, p4, p5, p6, p7, p8] = std::forward<T>(object);
return std::tuple(p1, p2, p3, p4, p5, p6, p7, p8);
} else if constexpr(is_braces_constructible<type, any_type, any_type, any_type, any_type, any_type, any_type, any_type>{})
{
auto&& [p1, p2, p3, p4, p5, p6, p7] = std::forward<T>(object);
return std::tuple(p1, p2, p3, p4, p5, p6, p7);
} else if constexpr(is_braces_constructible<type, any_type, any_type, any_type, any_type, any_type, any_type>{})
{
auto&& [p1, p2, p3, p4, p5, p6] = std::forward<T>(object);
return std::tuple(p1, p2, p3, p4, p5, p6);
} else if constexpr(is_braces_constructible<type, any_type, any_type, any_type, any_type, any_type>{})
{
auto&& [p1, p2, p3, p4, p5] = std::forward<T>(object);
return std::tuple(p1, p2, p3, p4, p5);
} if constexpr(is_braces_constructible<type, any_type, any_type, any_type, any_type>{})
{
auto&& [p1, p2, p3, p4] = std::forward<T>(object);
return std::tuple(p1, p2, p3, p4);
} else if constexpr(is_braces_constructible<type, any_type, any_type, any_type>{})
{
auto&& [p1, p2, p3] = std::forward<T>(object);
return std::tuple(p1, p2, p3);
} else if constexpr(is_braces_constructible<type, any_type, any_type>{})
{
auto&& [p1, p2] = std::forward<T>(object);
return std::tuple(p1, p2);
} else if constexpr(is_braces_constructible<type, any_type>{})
{
auto&& [p1] = std::forward<T>(object);
return std::tuple(p1);
}
else {
return std::tuple{};
}
}
#include <string>
#include <iostream>
int main() {
struct foo {
int p1;
std::string p2;
};
auto tuple = to_tuple(foo{42, "test"});
static_assert(std::is_same<std::tuple<int, std::string>, decltype(tuple)>{});
std::cout << std::get<0>(tuple) << '\n';
std::cout << std::get<1>(tuple) << '\n';
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment