1
0
forked from Alepha/Alepha

Fix the off-by-one computation for empty bases.

Instead of counting as we go, just build it, and then count.
This commit is contained in:
2021-10-28 03:34:02 -04:00
parent bdd222c4d5
commit 3f5b5f692e

View File

@ -12,6 +12,7 @@ static_assert( __cplusplus > 201700, "C++17 Required" );
#include <Alepha/Reflection/aggregate_initialization.h>
#include <Alepha/Meta/overload.h>
#include <Alepha/Meta/type_value.h>
namespace Alepha::Hydrogen::Reflection
{
@ -91,6 +92,12 @@ namespace Alepha::Hydrogen::Reflection
//template< typename T > constexpr operator T ()= delete;
};
template< typename T >
constexpr bool is_empty_base_v= false;
template< typename T >
constexpr bool is_empty_base_v< empty_base< T > >{ true };
template< typename Tuple, std::size_t baseCount, std::size_t totalCount >
constexpr void
check_tuple()
@ -134,23 +141,46 @@ namespace Alepha::Hydrogen::Reflection
template< typename T, typename Tuple >
constexpr bool is_constructible_from_tuple_v= is_constructible_from_tuple< T, Tuple >::value;
template< typename T, typename InitTuple, std::size_t index= 0, typename= std::enable_if_t< std::is_aggregate_v< T > > >
constexpr auto
build_base_tuple()
{
constexpr auto init_size= aggregate_initializer_size_v< T >;
using DeeperTuple= decltype( build_init_tuple< T, index, init_size >() );
if constexpr( is_constructible_from_tuple_v< T, DeeperTuple > )
{
return build_base_tuple< T, DeeperTuple, index + 1 >();
}
else return Meta::type_value< InitTuple >{};
}
template< typename ... Args, typename First >
constexpr std::size_t
count_empty_bases( Meta::type_value< std::tuple< First, Args... > > )
{
if constexpr( is_empty_base_v< First > ) return 1 + count_empty_bases( Meta::type_value< std::tuple< Args... > >{} );
else return 0;
}
constexpr std::size_t
count_empty_bases( Meta::type_value< std::tuple<> > )
{
return 0;
}
template< typename T, std::size_t index= 0, typename= std::enable_if_t< std::is_aggregate_v< T > > >
constexpr std::size_t
count_empty_bases()
{
constexpr auto init_size= aggregate_initializer_size_v< T >;
if constexpr( is_constructible_from_tuple_v< T, decltype( build_init_tuple< T, index, init_size >() ) > )
{
return 1 + count_empty_bases< T, index + 1 >();
}
else return 0;
return count_empty_bases( build_base_tuple< T, decltype( build_init_tuple< T, 0, aggregate_initializer_size_v< T > > ) >() );
}
namespace exports
{
template< typename T >
struct aggregate_empty_bases : std::integral_constant< std::size_t, count_empty_bases< T >() - 1 > {};
struct aggregate_empty_bases : std::integral_constant< std::size_t, count_empty_bases< T >() > {};
template< typename T >
constexpr std::size_t aggregate_empty_bases_v= aggregate_empty_bases< T >::value;