forked from Alepha/Alepha
Add tagged ctor check support.
This commit is contained in:
@ -1 +1,2 @@
|
|||||||
add_subdirectory( tuplizeAggregate.test )
|
add_subdirectory( tuplizeAggregate.test )
|
||||||
|
add_subdirectory( tagged_ctor_size.test )
|
||||||
|
@ -6,3 +6,12 @@ static_assert( __cplusplus > 2020'99 );
|
|||||||
|
|
||||||
// This file will eventually contain all of the constants that control how much generated code the
|
// This file will eventually contain all of the constants that control how much generated code the
|
||||||
// C++17 Reflection system will geeerate.
|
// C++17 Reflection system will geeerate.
|
||||||
|
|
||||||
|
// Note: not exported!
|
||||||
|
namespace Alepha::Hydrogen::Reflection ::detail:: config_m
|
||||||
|
{
|
||||||
|
namespace C
|
||||||
|
{
|
||||||
|
const std::size_t max_ctor_size= 32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
95
Reflection/tagged_ctor_size.h
Normal file
95
Reflection/tagged_ctor_size.h
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
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_size_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 has_tagged_ctor
|
||||||
|
: has_tagged_ctor< T, tag, cnt + 1 > {};
|
||||||
|
|
||||||
|
template< typename T, typename tag >
|
||||||
|
struct has_tagged_ctor< T, tag, C::max_ctor_size >
|
||||||
|
: std::false_type {};
|
||||||
|
|
||||||
|
template< typename T, typename tag, std::size_t depth >
|
||||||
|
requires ConstructibleWith< T, tag, depth >
|
||||||
|
struct has_tagged_ctor< T, tag, depth >
|
||||||
|
: std::true_type {};
|
||||||
|
|
||||||
|
namespace exports
|
||||||
|
{
|
||||||
|
template< typename T, typename tag >
|
||||||
|
constexpr std::size_t has_tagged_ctor_v= has_tagged_ctor< T, tag >::value;
|
||||||
|
|
||||||
|
template< typename T, typename tag >
|
||||||
|
struct has_tagged_ctor : std::bool_constant< has_tagged_ctor_v< T, tag > > {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Alepha::Hydrogen::Reflection::inline exports::inline tagged_ctor_size_m
|
||||||
|
{
|
||||||
|
using namespace detail::tagged_ctor_size_m::exports;
|
||||||
|
}
|
23
Reflection/tagged_ctor_size.test/0.cc
Normal file
23
Reflection/tagged_ctor_size.test/0.cc
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
static_assert( __cplusplus > 2020'99 );
|
||||||
|
|
||||||
|
#include <Alepha/Reflection/tagged_ctor_size.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_size_m;
|
||||||
|
static_assert( has_tagged_ctor_v< instance, tag > );
|
||||||
|
static_assert( not has_tagged_ctor_v< instance, tag2 > );
|
||||||
|
}
|
1
Reflection/tagged_ctor_size.test/CMakeLists.txt
Normal file
1
Reflection/tagged_ctor_size.test/CMakeLists.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
unit_test( 0 )
|
Reference in New Issue
Block a user