Created
October 26, 2019 20:45
-
-
Save talybin/2b1084e51ad36aa4caf308f75796137f 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'; | |
} |
Author
talybin
commented
Oct 26, 2019
•
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment