Created
March 18, 2019 19:54
-
-
Save ChemistAion/4118a3598f0b120b7f9c5884e9799a8b to your computer and use it in GitHub Desktop.
Aggregate arity calculations, based on: Björn Fahller and Anatoliy V. Tomilov implementations
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
// https://playfulprogramming.blogspot.com/2016/12/serializing-structs-with-c17-structured.html | |
// https://codereview.stackexchange.com/questions/142804/get-n-th-data-member-of-a-struct | |
// https://stackoverflow.com/questions/39768517/structured-bindings-width | |
// https://stackoverflow.com/questions/35463646/arity-of-aggregate-in-logarithmic-time | |
// https://stackoverflow.com/questions/38393302/returning-variadic-aggregates-struct-and-syntax-for-c17-variadic-template-c | |
#pragma once | |
#include <type_traits> | |
namespace Mockup::Serializer | |
{ | |
namespace Detail | |
{ | |
struct Instance | |
{ | |
template <typename Type> | |
operator Type () const; | |
}; | |
template<typename Aggregate, typename IndexSequence = std::index_sequence<>, typename = void> | |
struct ArityImpl : IndexSequence | |
{ | |
}; | |
template<typename Aggregate, std::size_t... Indices> | |
struct ArityImpl | |
< | |
Aggregate, std::index_sequence<Indices...>, | |
std::void_t<decltype(Aggregate{ (Indices, std::declval<Instance>())..., std::declval<Instance>() }) > | |
> | |
: ArityImpl<Aggregate, std::index_sequence<Indices..., sizeof... (Indices)>> | |
{ | |
}; | |
} | |
template<typename Aggregate> | |
constexpr std::size_t Arity() | |
{ | |
using aggregate_decay = std::remove_reference_t<std::remove_cv_t<Aggregate>>; | |
if constexpr | |
( | |
std::is_aggregate_v<aggregate_decay> && | |
std::is_standard_layout_v<aggregate_decay> && | |
!std::is_polymorphic_v<aggregate_decay> | |
) | |
{ | |
return Detail::ArityImpl<aggregate_decay>().size(); | |
} | |
else | |
{ | |
return 0; | |
} | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
// namespace Detail | |
// { | |
// struct Instance | |
// { | |
// template <typename Type, typename = std::enable_if_t<!std::is_lvalue_reference_v<Type>>> | |
// operator Type &&() const; | |
// | |
// template <typename Type, typename = std::enable_if_t<std::is_copy_constructible_v<Type>>> | |
// operator Type&() const; | |
// }; | |
// | |
// template <std::size_t Index = 0> | |
// static constexpr const Instance instance_ | |
// { | |
// }; | |
// | |
// //////////////////////////////////////////////////////////////////////////////// | |
// | |
// template <typename Type, std::size_t... Indicies> | |
// inline constexpr auto IsBraceConstructibleImpl(std::index_sequence<Indicies...>, Type*) -> decltype(Type{instance_<Indicies>...}, std::true_type{}); | |
// | |
// template <std::size_t... Indicies> | |
// inline constexpr std::false_type IsBraceConstructibleImpl(std::index_sequence<Indicies...>, ...); | |
// | |
// //////////////////////////////////////////////////////////////////////////////// | |
// | |
// template <typename Type, std::size_t... Indicies> | |
// inline constexpr auto IsParenthesisConstructibleImpl(std::index_sequence<Indicies...>, Type*) -> decltype(Type(instance_<Indicies>...), std::true_type{}); | |
// | |
// template <std::size_t... Indicies> | |
// inline constexpr std::false_type IsParenthesisConstructibleImpl(std::index_sequence<Indicies...>, ...); | |
// } | |
// | |
// template <typename Type, std::size_t Index> | |
// constexpr auto IsBraceConstructible() -> decltype(Detail::IsBraceConstructibleImpl(std::make_index_sequence<Index>(), static_cast<Type*>(nullptr))) | |
// { | |
// return {}; | |
// } | |
// | |
// template <typename Type, std::size_t Index> | |
// constexpr auto IsParenthesisConstructible() -> decltype(Detail::IsParenthesisConstructibleImpl(std::make_index_sequence<Index>(), static_cast<Type*>(nullptr))) | |
// { | |
// return {}; | |
// } | |
// | |
// //////////////////////////////////////////////////////////////////////////////// | |
// | |
// template <typename Type, typename = std::enable_if_t <std::is_class<Type>{} && std::is_empty<Type>{}>> | |
// constexpr std::integral_constant<std::size_t, 0> Arity() { return {}; } | |
// | |
// template<typename Type, typename = std::enable_if_t<IsBraceConstructible<Type, 1>() && !IsBraceConstructible<Type, 2>()>> | |
// constexpr std::integral_constant<std::size_t, 1> Arity() { return {}; } | |
// | |
// template<typename Type, typename = std::enable_if_t<IsBraceConstructible<Type, 2>() && !IsBraceConstructible<Type, 3>() && !IsParenthesisConstructible<Type, 2>()>> | |
// constexpr std::integral_constant<std::size_t, 2> Arity() { return {}; } | |
// | |
// template<typename Type, typename = std::enable_if_t<IsBraceConstructible<Type, 3>() && !IsBraceConstructible<Type, 4>() && !IsParenthesisConstructible<Type, 3>()>> | |
// constexpr std::integral_constant<std::size_t, 3> Arity() { return {}; } | |
// | |
// template<typename Type, typename = std::enable_if_t<IsBraceConstructible<Type, 4>() && !IsBraceConstructible<Type, 5>() && !IsParenthesisConstructible<Type, 4>()>> | |
// constexpr std::integral_constant<std::size_t, 4> Arity() { return {}; } | |
// | |
// template<typename Type, typename = std::enable_if_t<IsBraceConstructible<Type, 5>() && !IsBraceConstructible<Type, 6>() && !IsParenthesisConstructible<Type, 5>()>> | |
// constexpr std::integral_constant<std::size_t, 5> Arity() { return {}; } | |
// | |
// template<typename Type, typename = std::enable_if_t<IsBraceConstructible<Type, 6>() && !IsBraceConstructible<Type, 7>() && !IsParenthesisConstructible<Type, 6>()>> | |
// constexpr std::integral_constant<std::size_t, 6> Arity() { return {}; } | |
// | |
// template<typename Type, typename = std::enable_if_t<IsBraceConstructible<Type, 7>() && !IsBraceConstructible<Type, 8>() && !IsParenthesisConstructible<Type, 7>()>> | |
// constexpr std::integral_constant<std::size_t, 7> Arity() { return {}; } | |
// | |
// template<typename Type, typename = std::enable_if_t<IsBraceConstructible<Type, 8>() && !IsBraceConstructible<Type, 9>() && !IsParenthesisConstructible<Type, 8>()>> | |
// constexpr std::integral_constant<std::size_t, 8> Arity() { return {}; } | |
// | |
// template<typename Type, typename = std::enable_if_t<IsBraceConstructible<Type, 9>() && !IsBraceConstructible<Type, 10>() && !IsParenthesisConstructible<Type, 9>()>> | |
// constexpr std::integral_constant<std::size_t, 9> Arity() { return {}; } | |
// | |
// template<typename Type, typename = std::enable_if_t<IsBraceConstructible<Type, 10>() && !IsBraceConstructible<Type, 11>() && !IsParenthesisConstructible<Type, 10>()>> | |
// constexpr std::integral_constant<std::size_t, 10> Arity() { return {}; } | |
// | |
// template<typename Type, typename = std::enable_if_t<IsBraceConstructible<Type, 11>() && !IsBraceConstructible<Type, 12>() && !IsParenthesisConstructible<Type, 11>()>> | |
// constexpr std::integral_constant<std::size_t, 11> Arity() { return {}; } | |
// | |
// template<typename Type, typename = std::enable_if_t<IsBraceConstructible<Type, 12>() && !IsBraceConstructible<Type, 13>() && !IsParenthesisConstructible<Type, 12>()>> | |
// constexpr std::integral_constant<std::size_t, 12> Arity() { return {}; } | |
// | |
// template<typename Type, typename = std::enable_if_t<IsBraceConstructible<Type, 13>() && !IsBraceConstructible<Type, 14>() && !IsParenthesisConstructible<Type, 13>()>> | |
// constexpr std::integral_constant<std::size_t, 13> Arity() { return {}; } | |
// | |
// template<typename Type, typename = std::enable_if_t<IsBraceConstructible<Type, 14>() && !IsBraceConstructible<Type, 15>() && !IsParenthesisConstructible<Type, 14>()>> | |
// constexpr std::integral_constant<std::size_t, 14> Arity() { return {}; } | |
// | |
// template<typename Type, typename = std::enable_if_t<IsBraceConstructible<Type, 15>() && !IsBraceConstructible<Type, 16>() && !IsParenthesisConstructible<Type, 15>()>> | |
// constexpr std::integral_constant<std::size_t, 15> Arity() { return {}; } | |
// | |
// template<typename Type, typename = std::enable_if_t<IsBraceConstructible<Type, 16>() && !IsBraceConstructible<Type, 17>() && !IsParenthesisConstructible<Type, 16>()>> | |
// constexpr std::integral_constant<std::size_t, 16> Arity() { return {}; } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment