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:
@ -12,6 +12,7 @@ static_assert( __cplusplus > 201700, "C++17 Required" );
|
|||||||
#include <Alepha/Reflection/aggregate_initialization.h>
|
#include <Alepha/Reflection/aggregate_initialization.h>
|
||||||
|
|
||||||
#include <Alepha/Meta/overload.h>
|
#include <Alepha/Meta/overload.h>
|
||||||
|
#include <Alepha/Meta/type_value.h>
|
||||||
|
|
||||||
namespace Alepha::Hydrogen::Reflection
|
namespace Alepha::Hydrogen::Reflection
|
||||||
{
|
{
|
||||||
@ -91,6 +92,12 @@ namespace Alepha::Hydrogen::Reflection
|
|||||||
//template< typename T > constexpr operator T ()= delete;
|
//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 >
|
template< typename Tuple, std::size_t baseCount, std::size_t totalCount >
|
||||||
constexpr void
|
constexpr void
|
||||||
check_tuple()
|
check_tuple()
|
||||||
@ -134,23 +141,46 @@ namespace Alepha::Hydrogen::Reflection
|
|||||||
template< typename T, typename Tuple >
|
template< typename T, typename Tuple >
|
||||||
constexpr bool is_constructible_from_tuple_v= is_constructible_from_tuple< T, Tuple >::value;
|
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 > > >
|
template< typename T, std::size_t index= 0, typename= std::enable_if_t< std::is_aggregate_v< T > > >
|
||||||
constexpr std::size_t
|
constexpr std::size_t
|
||||||
count_empty_bases()
|
count_empty_bases()
|
||||||
{
|
{
|
||||||
constexpr auto init_size= aggregate_initializer_size_v< T >;
|
return count_empty_bases( build_base_tuple< T, decltype( build_init_tuple< T, 0, 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace exports
|
namespace exports
|
||||||
{
|
{
|
||||||
template< typename T >
|
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 >
|
template< typename T >
|
||||||
constexpr std::size_t aggregate_empty_bases_v= aggregate_empty_bases< T >::value;
|
constexpr std::size_t aggregate_empty_bases_v= aggregate_empty_bases< T >::value;
|
||||||
|
|||||||
Reference in New Issue
Block a user