OSSIA
Open Scenario System for Interactive Application
to_tuple.hpp
1 #pragma once
2 #include <boost/preprocessor/repetition/repeat.hpp>
3 
4 #include <cassert>
5 #include <tuple>
6 #include <type_traits>
7 // Taken from
8 // https://www.reddit.com/r/cpp/comments/4yp7fv/c17_structured_bindings_convert_struct_to_a_tuple/
9 
10 namespace ossia
11 {
12 namespace detail
13 {
14 struct any_type
15 {
16  template <class T>
17  constexpr operator T();
18 };
19 #pragma clang diagnostic push
20 #pragma clang diagnostic ignored "-Wmissing-field-initializers"
21 template <class T, std::size_t... I>
22 decltype(void(T{(I, std::declval<any_type>())...}), std::true_type{})
23  test_is_braces_constructible_n(std::index_sequence<I...>);
24 #pragma clang diagnostic pop
25 template <class, class...>
26 std::false_type test_is_braces_constructible_n(...);
27 template <class T, std::size_t N>
28 using is_braces_constructible_n
29  = decltype(test_is_braces_constructible_n<T>(std::make_index_sequence<N>{}));
30 
31 template <class T, std::size_t L = 0u, std::size_t R = sizeof(T) + 1u>
32 constexpr std::size_t to_tuple_size_f()
33 {
34  constexpr std::size_t M = (L + R) / 2u;
35  if constexpr(M == 0)
36  return std::is_empty<T>{} ? 0u : throw "Unable to determine number of elements";
37  else if constexpr(L == M)
38  return M;
39  else if constexpr(is_braces_constructible_n<T, M>{})
40  return to_tuple_size_f<T, M, R>();
41  else
42  return to_tuple_size_f<T, L, M>();
43 }
44 template <class T>
45 using to_tuple_size = std::integral_constant<std::size_t, to_tuple_size_f<T>()>;
46 
47 #ifndef TO_TUPLE_MAX
48 #define TO_TUPLE_MAX 5
49 #endif
50 
51 template <class T>
52 auto to_tuple_impl(T&&, std::integral_constant<std::size_t, 0>) noexcept
53 {
54  return std::make_tuple();
55 }
56 
57 #define TO_TUPLE_P(Z, N, _) , p##N
58 #define TO_TUPLE_SPECIALIZATION(Z, N, _) \
59  template <class T> \
60  auto to_tuple_impl(T&& object, std::integral_constant<std::size_t, N + 1>) noexcept \
61  { \
62  auto&& [p BOOST_PP_REPEAT_##Z(N, TO_TUPLE_P, nil)] = object; \
63  return std::make_tuple(p BOOST_PP_REPEAT_##Z(N, TO_TUPLE_P, nil)); \
64  }
65 BOOST_PP_REPEAT(TO_TUPLE_MAX, TO_TUPLE_SPECIALIZATION, nil)
66 #undef TO_TUPLE_SPECIALIZATION
67 #undef TO_TUPLE_P
68 
69 template <
70  class T, class = struct current_value, std::size_t = TO_TUPLE_MAX,
71  class = struct required_value, std::size_t N>
72 auto to_tuple_impl(T&&, std::integral_constant<std::size_t, N>) noexcept
73 {
74  static_assert(N <= TO_TUPLE_MAX, "Please increase TO_TUPLE_MAX");
75 }
76 }
77 
78 template <
79  class T, class = std::enable_if_t<
80  std::is_class<T>::value && std::is_standard_layout<T>::value>>
81 auto to_tuple(T&& object) noexcept
82 {
83  return detail::to_tuple_impl(
84  std::forward<T>(object), detail::to_tuple_size<std::decay_t<T>>{});
85 }
86 }
Definition: git_info.h:7