-
-
Save westfly/a3235014fa1e2a98abeb3c0e44ae1ccf to your computer and use it in GitHub Desktop.
Struct to tuple conversion (CppCon 2019, Kris Jusiak)
This file contains hidden or 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> | |
#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