1
0
forked from Alepha/Alepha

Tagged ctor count.

This commit is contained in:
2024-03-18 16:14:15 -04:00
parent d0fc98de71
commit 626a341821
4 changed files with 116 additions and 0 deletions

View File

@ -1,2 +1,3 @@
add_subdirectory( tuplizeAggregate.test ) add_subdirectory( tuplizeAggregate.test )
add_subdirectory( has_tagged_ctor.test ) add_subdirectory( has_tagged_ctor.test )
add_subdirectory( tagged_ctor_count.test )

View File

@ -0,0 +1,92 @@
static_assert( __cplusplus > 2020'99 );
#pragma once
#include <Alepha/Alepha.h>
#include <tuple>
#include <utility>
#include <type_traits>
#include <Alepha/Concepts.h>
#include <Alepha/Reflection/detail/config.h>
namespace Alepha::Hydrogen::Reflection ::detail:: tagged_ctor_count_m
{
inline namespace exports {}
namespace C
{
using namespace Reflection::detail::config_m::C;
}
// Basic methodology here: I probe the number of arguments that an object can be constructed with, given the tag.
// I don't care what they actually are, as there's no easy way to hoist out what they are. However, for an
// object ctor, we have to get the exact right number.
// Therefore we just wind up finding the smallest-ordinality ctor with that tag.
// The basic adaptable argument. Because it pretends to be anything, it can be used as a parameter in invoking
// any initialization method.
template< typename Forbidden >
struct argument
{
template< typename T >
requires( not Concepts::SameAs< T, Forbidden > )
constexpr operator T ();
};
template< typename T, typename ... Args >
requires Concepts::ConstructibleFrom< T, Args... >
constexpr void construct( const std::tuple< Args... > & );
template< typename T, typename Tuple >
concept ConstructibleWithTuple=
requires( Tuple tup )
{
{ construct< T >( tup ) };
};
template< typename Forbidden, typename Seq >
struct expand;
template< typename Forbidden, std::size_t ... Ints >
struct expand< Forbidden, std::index_sequence< Ints... > >
{
using type= decltype( std::make_tuple( ( Ints, argument< Forbidden >{} )... ) );
};
template< typename Forbidden, std::size_t argcnt >
using expand_t= typename expand< Forbidden, std::make_index_sequence< argcnt > >::type;
template< typename T, typename tag, std::size_t args >
concept ConstructibleWith=
ConstructibleWithTuple< T, decltype( std::tuple_cat( std::declval< expand_t< T, args > >(), std::declval< std::tuple< tag > >() ) ) >;
// The first step is to just start it all off with a blank sequence and walk forward from there.
// The default arguments cause it to start with the blank sequence, even if it doesn't match this
// case in the specialization selection.
template< typename T, typename tag, std::size_t cnt= 0 >
struct tagged_ctor_count
: tagged_ctor_count< T, tag, cnt + 1 > {};
template< typename T, typename tag, std::size_t depth >
requires ConstructibleWith< T, tag, depth >
struct tagged_ctor_count< T, tag, depth >
// Size is 1 more than the depth we probed, since that also accounts for the tag.
: std::integral_constant< std::size_t, depth + 1 > {};
namespace exports
{
template< typename T, typename tag >
constexpr std::size_t tagged_ctor_count_v= tagged_ctor_count< T, tag >::value;
template< typename T, typename tag >
struct tagged_ctor_count : std::integral_constant< std::size_t, tagged_ctor_count_v< T, tag > > {};
}
}
namespace Alepha::Hydrogen::Reflection::inline exports::inline tagged_ctor_count_m
{
using namespace detail::tagged_ctor_count_m::exports;
}

View File

@ -0,0 +1,22 @@
static_assert( __cplusplus > 2020'99 );
#include <Alepha/Reflection/tagged_ctor_count.h>
#include <Alepha/Testing/test.h>
#include <Alepha/types.h>
#include <Alepha/Meta/product_type_decay.h>
namespace
{
using namespace Alepha::Testing::literals;
struct tag {};
struct tag2 {};
struct instance
{
explicit instance( int a, float b, char c, double d, tag t );
};
using namespace Alepha::Reflection::exports::tagged_ctor_count_m;
static_assert( tagged_ctor_count_v< instance, tag > == 5 );
}

View File

@ -0,0 +1 @@
unit_test( 0 )