Skip to content

Instantly share code, notes, and snippets.

@boatilus
Created August 25, 2016 18:28
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 boatilus/2624a244bbecc290fe6a7b942b2f972c to your computer and use it in GitHub Desktop.
Save boatilus/2624a244bbecc290fe6a7b942b2f972c to your computer and use it in GitHub Desktop.
#include <tuple>
#include <type_traits>
#include <cassert>
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>
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>{}) {
auto&& [p1, p2, p3, p4] = object;
return std::make_tuple(p1, p2, p3, p4);
} else if constexpr(is_braces_constructible<type, any_type, any_type, any_type>{}) {
auto&& [p1, p2, p3] = object;
return std::make_tuple(p1, p2, p3);
} else if constexpr(is_braces_constructible<type, any_type, any_type>{}) {
auto&& [p1, p2] = object;
return std::make_tuple(p1, p2);
} else if constexpr(is_braces_constructible<type, any_type>{}) {
auto&& [p1] = object;
return std::make_tuple(p1);
} else {
return std::make_tuple();
}
}
int main() {
{
struct s {
int p1;
double p2;
};
auto t = to_tuple(s{1, 2.0});
static_assert(std::is_same<std::tuple<int, double>, decltype(t)>{});
assert(1 == std::get<0>(t));
assert(2.0 == std::get<1>(t));
}
{
struct s {
struct nested { } p1;
int p2;
int p3;
s* p4;
};
auto t = to_tuple(s{s::nested{}, 42, 87, nullptr});
static_assert(std::is_same<std::tuple<s::nested, int, int, s*>, decltype(t)>{});
assert(42 == std::get<1>(t));
assert(87 == std::get<2>(t));
assert(nullptr == std::get<3>(t));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment