Skip to content

Instantly share code, notes, and snippets.

@ChemistAion
Created March 18, 2019 19:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ChemistAion/4118a3598f0b120b7f9c5884e9799a8b to your computer and use it in GitHub Desktop.
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
// 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