Pourrait-on m’expliquer comment ce code fonctionne ? Plus particulierment le fonctionnement de arg_t
et de num_constructor_args
.
template <typename...> struct list_t {};
namespace detail {
template <typename T, std::size_t N> struct member {
friend constexpr auto member_type(member<T, N>);
};
template <typename T, std::size_t N, typename U>
struct set_member_type : std::true_type {
friend constexpr auto member_type(member<T, N>) { return U{}; }
};
template <typename T, std::size_t N> struct arg_t {
template <typename U>
constexpr operator U() const noexcept(std::enable_if_t<not std::is_same_v<T, U>, set_member_type<T, N, U>>::value);
};
template <typename T, typename... TArgs>
constexpr auto is_brace_constructible(int) -> decltype(T{TArgs{}...}, std::true_type{});
template <typename T, typename... TArgs>
constexpr auto is_brace_constructible(...) -> std::false_type;
template <typename T, auto... Is>
constexpr auto is_constructible(std::index_sequence<Is...>) -> decltype(is_brace_constructible<T, arg_t<T, Is>...>(0));
template <typename T, std::size_t L = 0u, std::size_t H = sizeof(T) + 1u>
constexpr auto num_constructor_args() -> std::size_t {
if constexpr (H - L == 1u) {
return L;
} else {
constexpr auto M = (L + H + 1u) / 2u;
if constexpr (decltype(is_constructible<T>(std::make_index_sequence<M>{})){}) {
return num_constructor_args<T, M, H>();
} else {
return num_constructor_args<T, L, M>();
}
}
}
template <typename T, auto... Is>
constexpr auto constructor_args(std::index_sequence<Is...>) -> list_t<decltype(member_type(member<T, Is>{}))...>;
template <typename T>
constexpr auto constructor_args() -> list_t<>;
} // namespace detail
template <typename T>
using num_members_t = std::integral_constant<std::size_t, detail::num_constructor_args<T>()>;
template <typename T>
using members_list_t = decltype(detail::constructor_args<T>(std::make_index_sequence<num_members_t<T>::value>{}));
struct Foo {
int a;
bool b;
char c;
double d;
std::string e;
};
static_assert(std::is_same_v<members_list_t<Foo>, list_t<int, bool, char, double, std::string>>);
+0
-0