How to define arity of an aggregate in logarithmic (at least base two) compilation time (strictly speaking, in logarithmic number of instantiations)?
What I can do currently is to achieve desired in a linear time:
#include <type_traits>
#include <utility>
struct filler { template< typename type > operator type (); };
template< typename A, typename index_sequence = std::index_sequence<>, typename = void >
struct aggregate_arity
: index_sequence
{
};
template< typename A, std::size_t ...indices >
struct aggregate_arity< A, std::index_sequence< indices... >, std::__void_t< decltype(A{(indices, std::declval< filler >())..., std::declval< filler >()}) > >
: aggregate_arity< A, std::index_sequence< indices..., sizeof...(indices) > >
{
};
struct A0 {};
struct A1 { double x; };
struct A2 { int i; char c; };
struct C50 { template< typename ...Args, typename = std::enable_if_t< (sizeof...(Args) < 51) > > C50(Args &&...) { ; } };
static_assert(aggregate_arity< A0 >::size() == 0);
static_assert(aggregate_arity< A1 >::size() == 1);
static_assert(aggregate_arity< A2 >::size() == 2);
static_assert(aggregate_arity< C50 >::size() == 50);
Please correct me if term "arity" is poor.
I think it is possible in principle: firstly one need to double arity trials starting from one until SFINAE failed (surely, in soft manner), then use bisection.
See Question&Answers more detail:os