diff --git a/Algorithm/string_distance.cc b/Algorithm/string_distance.cc index f7f5b31..e7b9d12 100644 --- a/Algorithm/string_distance.cc +++ b/Algorithm/string_distance.cc @@ -10,7 +10,7 @@ static_assert( __cplusplus > 2020'99 ); #include #include -namespace Alepha::Hydrogen::Algorithm::detail::string_distance_m +namespace Alepha::Hydrogen::Algorithm ::detail:: string_distance_m { namespace { diff --git a/AutoRAII.h b/AutoRAII.h index 09f60a1..bd67d61 100644 --- a/AutoRAII.h +++ b/AutoRAII.h @@ -9,78 +9,73 @@ static_assert( __cplusplus > 2020'99 ); #include -namespace Alepha::Hydrogen +namespace Alepha::Hydrogen ::detail:: AutoRAII_m { - inline namespace exports { inline namespace AutoRAII_m {} } - - namespace detail::AutoRAII_m + inline namespace exports { - inline namespace exports + template< typename T, typename Dtor= std::function< void ( T ) > > + class AutoRAII : boost::noncopyable { - template< typename T, typename Dtor= std::function< void ( T ) > > - class AutoRAII : boost::noncopyable - { - private: - Dtor dtor; - T value; + private: + Dtor dtor; + T value; - public: - ~AutoRAII() + public: + ~AutoRAII() + { + if constexpr( std::is_same_v< Dtor, std::function< void ( T ) > > ) { - if constexpr( std::is_same_v< Dtor, std::function< void ( T ) > > ) - { - if( dtor == nullptr ) return; - } - dtor( value ); + if( dtor == nullptr ) return; } + dtor( value ); + } - template< typename Ctor > - explicit AutoRAII( Ctor ctor, Dtor dtor ) : dtor( std::move( dtor ) ), value( ctor() ) {} + template< typename Ctor > + explicit AutoRAII( Ctor ctor, Dtor dtor ) : dtor( std::move( dtor ) ), value( ctor() ) {} - operator const T &() const { return value; } + operator const T &() const { return value; } - decltype( auto ) - operator *() const - requires( std::is_pointer_v< T > ) + decltype( auto ) + operator *() const + requires( std::is_pointer_v< T > ) + { + return *value; + } + + decltype( auto ) + operator->() const + requires( std::is_pointer_v< T > ) + { + return value; + } + }; + + template< typename Dtor > + class AutoRAII< void, Dtor > : boost::noncopyable + { + private: + Dtor dtor; + + public: + ~AutoRAII() + { + if constexpr( std::is_same_v< Dtor, std::function< void () > > ) { - return *value; + if( dtor == nullptr ) return; } - - decltype( auto ) - operator->() const - requires( std::is_pointer_v< T > ) - { - return value; - } - }; + dtor(); + } - template< typename Dtor > - class AutoRAII< void, Dtor > : boost::noncopyable - { - private: - Dtor dtor; + template< typename Ctor > + explicit AutoRAII( Ctor ctor, Dtor dtor ) : dtor( std::move( dtor ) ) { ctor(); } + }; - public: - ~AutoRAII() - { - if constexpr( std::is_same_v< Dtor, std::function< void () > > ) - { - if( dtor == nullptr ) return; - } - dtor(); - } - - template< typename Ctor > - explicit AutoRAII( Ctor ctor, Dtor dtor ) : dtor( std::move( dtor ) ) { ctor(); } - }; - - template< typename Ctor, typename Dtor > - explicit AutoRAII( Ctor ctor, Dtor ) -> AutoRAII< decltype( ctor() ), Dtor >; - } - } - - namespace exports::AutoRAII_m - { - using namespace detail::AutoRAII_m::exports; + template< typename Ctor, typename Dtor > + explicit AutoRAII( Ctor ctor, Dtor ) -> AutoRAII< decltype( ctor() ), Dtor >; } } + +namespace Alepha::Hydrogen::inline exports::inline AutoRAII_m +{ + using namespace detail::AutoRAII_m::exports; +} diff --git a/Console.cc b/Console.cc index 4884630..4c6e0d7 100644 --- a/Console.cc +++ b/Console.cc @@ -46,7 +46,7 @@ namespace Alepha::Hydrogen ::detail:: Console_m { using namespace std::literals::string_literals; - using namespace Utility::exports::evaluation_helpers; + using namespace Utility::exports::evaluation_helpers_m; using Utility::StaticValue; namespace C diff --git a/DataChain.h b/DataChain.h index b7216f5..6f33edd 100644 --- a/DataChain.h +++ b/DataChain.h @@ -12,7 +12,7 @@ static_assert( __cplusplus > 2020'99 ); #include "Buffer.h" #include "Blob.h" -namespace Alepha::inline Cavorite ::detail:: data_chain +namespace Alepha::inline Cavorite ::detail:: DataChain_m { inline namespace exports { diff --git a/IOStreams/IStreamable.h b/IOStreams/IStreamable.h index 28c69f4..018774f 100644 --- a/IOStreams/IStreamable.h +++ b/IOStreams/IStreamable.h @@ -15,7 +15,7 @@ static_assert( __cplusplus > 2020'99 ); #include "delimiters.h" -namespace Alepha::Hydrogen::IOStreams ::detail:: istreamable_module +namespace Alepha::Hydrogen::IOStreams ::detail:: IStreamable_m { inline namespace exports { @@ -57,7 +57,7 @@ namespace Alepha::Hydrogen::IOStreams ::detail:: istreamable_module } } -namespace Alepha::Hydrogen::IOStreams::inline exports::inline istreamable_module +namespace Alepha::Hydrogen::IOStreams::inline exports::inline IStreamable_m { - using namespace detail::istreamable_module::exports; + using namespace detail::IStreamable_m::exports; } diff --git a/IOStreams/OStreamable.h b/IOStreams/OStreamable.h index 6f8b658..cf0a153 100644 --- a/IOStreams/OStreamable.h +++ b/IOStreams/OStreamable.h @@ -15,7 +15,7 @@ static_assert( __cplusplus > 2020'99 ); #include -namespace Alepha::Hydrogen::IOStreams ::detail:: ostreamable_module +namespace Alepha::Hydrogen::IOStreams ::detail:: OStreamable_m { inline namespace exports { @@ -54,8 +54,8 @@ namespace Alepha::Hydrogen::IOStreams ::detail:: ostreamable_module } } -namespace Alepha::Hydrogen::IOStreams::inline exports::inline ostreamable_module +namespace Alepha::Hydrogen::IOStreams::inline exports::inline OStreamable_m { - using namespace detail::ostreamable_module::exports; + using namespace detail::OStreamable_m::exports; } diff --git a/IOStreams/StackableStreambuf.cc b/IOStreams/StackableStreambuf.cc index c7efdab..007b76d 100644 --- a/IOStreams/StackableStreambuf.cc +++ b/IOStreams/StackableStreambuf.cc @@ -4,7 +4,7 @@ static_assert( __cplusplus > 2020'99 ); #include -namespace Alepha::Hydrogen::IOStreams::detail::stackable_streambuf +namespace Alepha::Hydrogen::IOStreams::detail::StackableStreambuf_m { namespace { diff --git a/IOStreams/StackableStreambuf.h b/IOStreams/StackableStreambuf.h index 5dfd60f..8e0a74f 100644 --- a/IOStreams/StackableStreambuf.h +++ b/IOStreams/StackableStreambuf.h @@ -10,7 +10,7 @@ static_assert( __cplusplus > 2020'99 ); #include #include -namespace Alepha::Hydrogen::IOStreams ::detail:: stackable_streambuf +namespace Alepha::Hydrogen::IOStreams ::detail:: StackableStreambuf_m { inline namespace exports { @@ -63,7 +63,7 @@ namespace Alepha::Hydrogen::IOStreams ::detail:: stackable_streambuf } } -namespace Alepha::Hydrogen::IOStreams::inline exports::inline stackable_streambuf +namespace Alepha::Hydrogen::IOStreams::inline exports::inline StackableStreambuf_m { - using namespace detail::stackable_streambuf::exports; + using namespace detail::StackableStreambuf_m::exports; } diff --git a/IOStreams/StreamState.h b/IOStreams/StreamState.h index b3263a4..e575284 100644 --- a/IOStreams/StreamState.h +++ b/IOStreams/StreamState.h @@ -10,7 +10,7 @@ static_assert( __cplusplus > 2020'99 ); #include -namespace Alepha::Hydrogen::IOStreams ::detail:: stream_state +namespace Alepha::Hydrogen::IOStreams ::detail:: StreamState_m { inline namespace exports { @@ -124,7 +124,7 @@ namespace Alepha::Hydrogen::IOStreams ::detail:: stream_state }; } -namespace Alepha::Hydrogen::IOStreams::inline exports::inline stream_state +namespace Alepha::Hydrogen::IOStreams::inline exports::inline StreamState_m { - using namespace detail::stream_state::exports; + using namespace detail::StreamState_m::exports; } diff --git a/Meta/Meta.test/traits.cc b/Meta/Meta.test/traits.cc index 6a03c81..30e36f3 100644 --- a/Meta/Meta.test/traits.cc +++ b/Meta/Meta.test/traits.cc @@ -13,7 +13,7 @@ static_assert( __cplusplus > 2020'99 ); namespace { - using namespace Alepha::Utility::exports::evaluation_helpers; + using namespace Alepha::Utility::exports::evaluation_helpers_m; using namespace Alepha::Testing::literals; using std::begin, std::end; diff --git a/Meta/dep_value.h b/Meta/dep_value.h index f825a53..2b961c4 100644 --- a/Meta/dep_value.h +++ b/Meta/dep_value.h @@ -4,21 +4,16 @@ static_assert( __cplusplus > 2020'99 ); #include -namespace Alepha::Hydrogen::Meta +namespace Alepha::Hydrogen::Meta ::detail:: dep_value_m { - inline namespace exports { inline namespace dependent_value {} } - - namespace detail::dependent_value + inline namespace exports { - inline namespace exports - { - template< auto value, typename T > - constexpr auto dep_value= value; - } - } - - namespace exports::dependent_value - { - using namespace detail::dependent_value::exports; + template< auto value, typename T > + constexpr auto dep_value= value; } } + +namespace Alepha::Hydrogen::Meta::inline exports::inline dep_value_m +{ + using namespace detail::dep_value_m::exports; +} diff --git a/Meta/find.h b/Meta/find.h index d83448d..8c435c3 100644 --- a/Meta/find.h +++ b/Meta/find.h @@ -9,36 +9,31 @@ static_assert( __cplusplus > 2020'99 ); #include #include -namespace Alepha::Hydrogen::Meta +namespace Alepha::Hydrogen::Meta ::detail:: find_algo_m { - inline namespace exports { inline namespace find_algos {} } - - namespace detail::find_algos + inline namespace exports { - inline namespace exports + template< typename Iter, typename Predicate > + constexpr bool + find_if( const Iter first, const Iter last, Predicate pred ) { - template< typename Iter, typename Predicate > - constexpr bool - find_if( const Iter first, const Iter last, Predicate pred ) + for( Iter pos= first; pos != last; ++pos ) { - for( Iter pos= first; pos != last; ++pos ) - { - if( pred( *pos ) ) return true; - } - return false; + if( pred( *pos ) ) return true; } + return false; + } - template< typename Iter, typename Value > - constexpr bool - find( const Iter first, const Iter last, const Value value ) - { - return find_if( first, last, Meta::bind1st( std::equal_to{}, value ) ); - } + template< typename Iter, typename Value > + constexpr bool + find( const Iter first, const Iter last, const Value value ) + { + return find_if( first, last, Meta::bind1st( std::equal_to{}, value ) ); } } - - namespace exports::find_algos - { - using namespace detail::find_algos::exports; - } +} + +namespace Alepha::Hydrogen::Meta::inline exports::inline find_algo_m +{ + using namespace detail::find_algo_m::exports; } diff --git a/Meta/functional.h b/Meta/functional.h index 78c30d1..298169d 100644 --- a/Meta/functional.h +++ b/Meta/functional.h @@ -6,51 +6,46 @@ static_assert( __cplusplus > 2020'99 ); #include -namespace Alepha::Hydrogen::Meta +namespace Alepha::Hydrogen::Meta ::detail:: functional_m { - inline namespace exports { inline namespace functional {} } - - namespace detail::functional + inline namespace exports { - inline namespace exports - { - template< typename MetaFunction, typename Arg > - constexpr auto bind1st( MetaFunction func, Arg arg ); - } - - template< typename MetaFunction, typename Arg > struct binder1st; - - template< typename MetaFunction, typename Arg1, typename Arg2 > - constexpr decltype( auto ) - invoke_call( MetaFunction func, Meta::type_value< Arg1 > arg1, Meta::type_value< Arg2 > arg2 ) - { - return func( arg1, arg2 ); - } - template< typename MetaFunction, typename Arg > - struct binder1st< MetaFunction, Meta::type_value< Arg > > - { - MetaFunction func; - Meta::type_value< Arg > arg; - - template< typename Second > - constexpr decltype( auto ) - operator () ( const Second &second ) - { - return invoke_call( func, arg, second ); - } - }; - - template< typename MetaFunction, typename Arg > - constexpr auto - exports::bind1st( MetaFunction func, Arg arg ) - { - return binder1st< MetaFunction, Arg >{ func, arg }; - } + constexpr auto bind1st( MetaFunction func, Arg arg ); } - namespace exports::functional + template< typename MetaFunction, typename Arg > struct binder1st; + + template< typename MetaFunction, typename Arg1, typename Arg2 > + constexpr decltype( auto ) + invoke_call( MetaFunction func, Meta::type_value< Arg1 > arg1, Meta::type_value< Arg2 > arg2 ) { - using namespace detail::functional::exports; + return func( arg1, arg2 ); + } + + template< typename MetaFunction, typename Arg > + struct binder1st< MetaFunction, Meta::type_value< Arg > > + { + MetaFunction func; + Meta::type_value< Arg > arg; + + template< typename Second > + constexpr decltype( auto ) + operator () ( const Second &second ) + { + return invoke_call( func, arg, second ); + } + }; + + template< typename MetaFunction, typename Arg > + constexpr auto + exports::bind1st( MetaFunction func, Arg arg ) + { + return binder1st< MetaFunction, Arg >{ func, arg }; } } + +namespace Alepha::Hydrogen::Meta::inline exports::inline functional_m +{ + using namespace detail::functional_m::exports; +} diff --git a/ProgramOptions.h b/ProgramOptions.h index c6edb00..1b51ced 100644 --- a/ProgramOptions.h +++ b/ProgramOptions.h @@ -100,7 +100,7 @@ namespace Alepha::Hydrogen ::detail:: ProgramOptions_m { inline namespace exports {} - using namespace Utility::exports::evaluation_helpers; + using namespace Utility::exports::evaluation_helpers_m; /*! * User created unique symbols can be bound to options to build classes of options. diff --git a/Reflection/aggregate_initializer_size.h b/Reflection/aggregate_initializer_size.h index 6bb052f..ca3cc54 100644 --- a/Reflection/aggregate_initializer_size.h +++ b/Reflection/aggregate_initializer_size.h @@ -10,7 +10,7 @@ static_assert( __cplusplus > 2020'99 ); #include -namespace Alepha::Hydrogen::Reflection ::detail:: aggregate_initializer_size_m +namespace Alepha::Hydrogen::Reflection ::detail:: aggregate_initializer_size_m { inline namespace exports {} diff --git a/Reflection/aggregate_members.h b/Reflection/aggregate_members.h index 263decc..e16b835 100644 --- a/Reflection/aggregate_members.h +++ b/Reflection/aggregate_members.h @@ -16,176 +16,171 @@ static_assert( __cplusplus > 2020'99 ); #include #include -namespace Alepha::Hydrogen::Reflection +namespace Alepha::Hydrogen::Reflection ::detail:: aggregate_members_m { - inline namespace exports { inline namespace aggregate_members {} } + inline namespace exports {} - namespace detail::aggregate_members + using Meta::overload; + + /*! + * Basic methodology here. + * + * The number of members in an aggregate is equal to the number of initializer parameters it takes less + * the number of empty base classes it has. In simple terms, this would be `init_terms< T > - empty_bases< T >`, + * However, it's not that simple. To do that the easy way, one might need get `std::tuple< InitTerms... >` and then compute + * which terms were bases. Now that gets a bit complicated, as in C++ one can't just directly get a tuple of initializer + * arguments (portably) to scoop out the arguments and analyze them one-by-one. One can, however, constrain the arguments + * one-by-one in templates. Those constraints cannot directly leak out the types they conclude, as that requires side + * effects. (Yes, template-friend-injection can be used here, but these mechanisms are extremely delicate. They're + * not really portable. Further, the way that constraints get instantiated for matching is prone to complications.) + * + * Instead, a side-stepping approach is required. It's trivial to ask: "Can this object be constructed from these + * N adaptive types, where the first one is constrained to be a base class of your object's type?" If yes, then + * this proves a (likely) empty base. One can just recursively iterate through more an more constrained adaptive + * types until the first non-base type is reached. At this point, there are no more than that many base classes. + * + * There may actually be fewer base classes, however. Consider: + * + * ``` + * struct SneakyBase {}; + * + * struct Complicated : SneakyBase + * { + * SneakyBase member; + * }; + * ``` + * In that case, a constrained adaptable argument would see two base types. Here is where a bit of C++ trivia and + * knowledge comes into play. C++ forbids repetition of a base class's type. Therefore the sequence of base classes + * cannot have repeats. The solution is to perform a nested exploration of instantiations of `checker` types which + * has each descent disable casting to `std::is_base_of_v` types which already have been expanded. Thus whatever + * count this expands to, it will be the correct empty-bases count. Then that count can be subtracted from the + * initializer list count. + * + * Note that this will not work with types that have non-empty bases, but those types cannot be decomposed, + * anyhow. Such types cannot have C++17 reflection performed on them. + * + * For the moment, computing a deep-dive on constrainted adaptable arguments is skipped. It's a lot more + * complicated than just counting empty bases. As long as the first actual member is not also a base class, + * this technique will work. + */ + + // The basic adaptable argument. Because it pretends to be anything, it can be used as a parameter in invoking + // any initialization method. + struct argument { template< typename T > constexpr operator T (); }; + + // Any empty-base-class argument. + template< typename Aggregate > + struct empty_base { - inline namespace exports {} - - using Meta::overload; - - /*! - * Basic methodology here. - * - * The number of members in an aggregate is equal to the number of initializer parameters it takes less - * the number of empty base classes it has. In simple terms, this would be `init_terms< T > - empty_bases< T >`, - * However, it's not that simple. To do that the easy way, one might need get `std::tuple< InitTerms... >` and then compute - * which terms were bases. Now that gets a bit complicated, as in C++ one can't just directly get a tuple of initializer - * arguments (portably) to scoop out the arguments and analyze them one-by-one. One can, however, constrain the arguments - * one-by-one in templates. Those constraints cannot directly leak out the types they conclude, as that requires side - * effects. (Yes, template-friend-injection can be used here, but these mechanisms are extremely delicate. They're - * not really portable. Further, the way that constraints get instantiated for matching is prone to complications.) - * - * Instead, a side-stepping approach is required. It's trivial to ask: "Can this object be constructed from these - * N adaptive types, where the first one is constrained to be a base class of your object's type?" If yes, then - * this proves a (likely) empty base. One can just recursively iterate through more an more constrained adaptive - * types until the first non-base type is reached. At this point, there are no more than that many base classes. - * - * There may actually be fewer base classes, however. Consider: - * - * ``` - * struct SneakyBase {}; - * - * struct Complicated : SneakyBase - * { - * SneakyBase member; - * }; - * ``` - * In that case, a constrained adaptable argument would see two base types. Here is where a bit of C++ trivia and - * knowledge comes into play. C++ forbids repetition of a base class's type. Therefore the sequence of base classes - * cannot have repeats. The solution is to perform a nested exploration of instantiations of `checker` types which - * has each descent disable casting to `std::is_base_of_v` types which already have been expanded. Thus whatever - * count this expands to, it will be the correct empty-bases count. Then that count can be subtracted from the - * initializer list count. - * - * Note that this will not work with types that have non-empty bases, but those types cannot be decomposed, - * anyhow. Such types cannot have C++17 reflection performed on them. - * - * For the moment, computing a deep-dive on constrainted adaptable arguments is skipped. It's a lot more - * complicated than just counting empty bases. As long as the first actual member is not also a base class, - * this technique will work. - */ - - // The basic adaptable argument. Because it pretends to be anything, it can be used as a parameter in invoking - // any initialization method. - struct argument { template< typename T > constexpr operator T (); }; - - // Any empty-base-class argument. - template< typename Aggregate > - struct empty_base - { - template< typename T > - requires - ( - true - and EmptyType< std::decay_t< T > > - and not SameAs< std::decay_t< T >, Aggregate > - and DerivedFrom< Aggregate, std::decay_t< T > > - ) - constexpr operator T (); - - //template< typename T > constexpr operator T ()= delete; - }; - template< typename T > - constexpr bool is_empty_base_v= false; + requires + ( + true + and EmptyType< std::decay_t< T > > + and not SameAs< std::decay_t< T >, Aggregate > + and DerivedFrom< Aggregate, std::decay_t< T > > + ) + constexpr operator T (); - template< typename T > - constexpr bool is_empty_base_v< empty_base< T > >{ true }; + //template< typename T > constexpr operator T ()= delete; + }; - template< typename Tuple, std::size_t baseCount, std::size_t totalCount > - constexpr void - check_tuple() + 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() + { + static_assert( std::tuple_size_v< Tuple > == totalCount ); + } + + template< typename Aggregate, std::size_t bases, std::size_t total > + constexpr auto + build_init_tuple() + { + static_assert( bases <= total ); + if constexpr( total == 0 ) return std::tuple{}; + else if constexpr( bases > 0 ) { - static_assert( std::tuple_size_v< Tuple > == totalCount ); + auto result= std::tuple_cat( std::tuple{ empty_base< Aggregate >{} }, build_init_tuple< Aggregate, bases - 1, total - 1 >() ); + check_tuple< decltype( result ), bases, total >(); + return result; } - - template< typename Aggregate, std::size_t bases, std::size_t total > - constexpr auto - build_init_tuple() + else { - static_assert( bases <= total ); - if constexpr( total == 0 ) return std::tuple{}; - else if constexpr( bases > 0 ) - { - auto result= std::tuple_cat( std::tuple{ empty_base< Aggregate >{} }, build_init_tuple< Aggregate, bases - 1, total - 1 >() ); - check_tuple< decltype( result ), bases, total >(); - return result; - } - else - { - static_assert( bases == 0 ); - auto result= std::tuple_cat( std::tuple{ argument{} }, build_init_tuple< Aggregate, 0, total - 1 >() ); - check_tuple< decltype( result ), bases, total >(); - return result; - } - } - - template< typename T, typename Tuple > - constexpr bool is_constructible_from_tuple_v= false; - - template< typename T, typename ... TupleArgs > - constexpr bool is_constructible_from_tuple_v< T, std::tuple< TupleArgs... > > - { - ConstructibleFrom< T, TupleArgs... > - }; - - template< Aggregate T, typename InitTuple, std::size_t index= 0 > - 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< Aggregate T, std::size_t index= 0 > - constexpr std::size_t - count_empty_bases() - { - 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 >() > {}; - - template< typename T > - constexpr std::size_t aggregate_empty_bases_v= aggregate_empty_bases< T >::value; - - template< typename T > - constexpr std::size_t aggregate_member_count_v= aggregate_initializer_size_v< T > - aggregate_empty_bases_v< T >; - - template< typename T > - struct aggregate_member_count : std::integral_constant< std::size_t, aggregate_member_count_v< T > > {}; + static_assert( bases == 0 ); + auto result= std::tuple_cat( std::tuple{ argument{} }, build_init_tuple< Aggregate, 0, total - 1 >() ); + check_tuple< decltype( result ), bases, total >(); + return result; } } - namespace exports::aggregate_members + template< typename T, typename Tuple > + constexpr bool is_constructible_from_tuple_v= false; + + template< typename T, typename ... TupleArgs > + constexpr bool is_constructible_from_tuple_v< T, std::tuple< TupleArgs... > > { - using namespace detail::aggregate_members::exports; + ConstructibleFrom< T, TupleArgs... > + }; + + template< Aggregate T, typename InitTuple, std::size_t index= 0 > + 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< Aggregate T, std::size_t index= 0 > + constexpr std::size_t + count_empty_bases() + { + 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 >() > {}; + + template< typename T > + constexpr std::size_t aggregate_empty_bases_v= aggregate_empty_bases< T >::value; + + template< typename T > + constexpr std::size_t aggregate_member_count_v= aggregate_initializer_size_v< T > - aggregate_empty_bases_v< T >; + + template< typename T > + struct aggregate_member_count : std::integral_constant< std::size_t, aggregate_member_count_v< T > > {}; } } + +namespace Alepha::Hydrogen::Reflection::inline exports::inline aggregate_members_m +{ + using namespace detail::aggregate_members_m::exports; +} diff --git a/Reflection/tuplizeAggregate.h b/Reflection/tuplizeAggregate.h index b966911..e308609 100644 --- a/Reflection/tuplizeAggregate.h +++ b/Reflection/tuplizeAggregate.h @@ -11,197 +11,192 @@ static_assert( __cplusplus > 2020'99 ); #include #include -namespace Alepha::Hydrogen::Reflection +namespace Alepha::Hydrogen::Reflection ::detail:: tuplizeAggregate_m { - inline namespace exports { inline namespace tuplize_aggregate {} } + inline namespace exports {} - namespace detail::tuplize_aggregate + template< typename T > + concept SalientMembers= + requires( const T &t ) { - inline namespace exports {} + { T::salient_members } -> ConvertibleTo< std::size_t >; + }; - template< typename T > - concept SalientMembers= - requires( const T &t ) - { - { T::salient_members } -> ConvertibleTo< std::size_t >; - }; - - template< typename T > - constexpr std::size_t - compute_salient_members_count_impl() - { - if constexpr( SalientMembers< T > ) return T::salient_members; - else return aggregate_member_count_v< std::decay_t< T > >; - } - - template< typename T > - constexpr std::size_t compute_salient_members_count_v= compute_salient_members_count_impl< T >(); - - namespace exports - { - /*! - * Deconstruct an aggregate object into a tie-based tuple pointing at its members. - * - * C++17's primary new reflection-oriented introduction is Structured Binding Declarations. - * What these let one do is to introduce a set of named variables that bind to each member - * of a (raw aggregate) `struct` in turn. This leads to some very interesting forms of - * "reflection" about what a user defined type is made of. Combined with the `std::is_aggregate` - * trait function and a way to determine the number of member objects, this provides a - * powerful new way to inspect any type. - * - * Structured Binding Declarations can also be used with arrays or types which implement a subset - * of the `std::tuple` interface. Those cases are not as interesting. We've always had the - * ability to inspect arrays via templates -- simple deduction operations work for that. And - * C++11's `std::tuple`s are already inspectable by their nature and types which implement a tuple-like - * interface are also easily inspected by pre-C++17 means. - * - * The most important thing C++17 Structured Binding brings to the language is the ability to - * (at compiletime) programmatically inspect any structure's members -- to learn their types, - * and with a bit of special effort, to learn their offsets. The names of those members are - * hidden, but their types are available, as is a way to work with all of them at once. Any - * Structured Binding is sufficient to do this -- one need only give a new name for each member of - * the type. `auto &[ a, b, c, d ]= someStruct;` is all that is needed and one has already performed - * an interesting feat of rudimentary reflection on the type `someStruct`. By loading those values - * into a tuple (by reference), by code such as `std::tie( a, b, c, d )`, a programmer can provide - * an anonymized, distilled reflection of the contents of that `struct`. This said, a library function - * which can decompose any `struct` into such a tie is very useful. `tuplizeAggregate` is exactly this. - * - * This function contains a pre-built set of such decompositions for structs of various sizes. C++17 - * does not permit arbitrarily sized Structured Bindings, and so a limit had to be placed. The limit - * is fairly generous, however. If an aggregate size which is greater than the pre-build maximum is - * provided, then the compile will fail on a `static_assert` indicating this. - * - * Unfortunately, as a declaration syntax, the number of members in a `struct`'s body cannot be inferred - * through SFINAE by this means. Normally the user must explicitly provide the number of member - * variables. However, combined with a pair of C++11 features (based upon variadic templates and - * aggregate initialization syntax) we can infer the number of memmber values via a set of helper - * templates (which can also be called directly.) - * - * This kind of reflection into an aggregate type can prove very useful. Code generators for - * serialization, conversion tools, universal utility functions, and much more can all be built in - * C++17, today, using this kind of reflection! There's no need to wait for C++23 or beyond when - * static reflection is added to the language. A great deal of desired reflection use cases can be - * attained today. One just need write some code generators in terms of `std::tuple` and `std::tie`, - * then make any overloads (perhaps using ADL hooking tricks) which call `Alepha::Reflection::tuplizeAggregate` - * and pass that result to the general tuple form. For serializers and such, other techniques such as - * `boost::core::demangle( typeid( instance ).name() )` can be used to get nice names for types when - * implementing universal serializers. In fact, this can be used as a crutch for serializing more - * complicated user types (with private data and such). Those types can produce an aggregate "view" - * of what they must serialize or deserialize, and then they can hand that view off to such code - * generators. And, of cousre, this need not apply just to serialization. - * - * @param agg Aggregate instance to decompose into a `std::tie` based `std::tuple`. - * @tparam aggregate_size The number of members in the aggregate argument `agg`'s definition. - * @tparam Aggregate The type of the aggregate to decompose. - */ - // TODO: Make `aggregate_size` deduced via `Reflection::aggregate_ctor...` means. - template< std::size_t aggregate_size, typename Aggregate, typename= std::enable_if_t< not std::is_rvalue_reference_v< Aggregate > > > - constexpr decltype( auto ) - tuplizeAggregate( Aggregate &&agg ) - { - static_assert( std::is_aggregate_v< std::decay_t< Aggregate > >, "`tuplizeAggregate` only can be used on aggregates" ); - - // TODO: Generate these cases via boost preprocessor, to cut down on repetition... - if constexpr( aggregate_size == 0 ) return std::tuple{}; - else if constexpr( aggregate_size == 1 ) - { - auto &[ a0 ]= agg; - return std::tie( a0 ); - } - else if constexpr( aggregate_size == 2 ) - { - auto &[ a0, a1 ]= agg; - return std::tie( a0, a1 ); - } - else if constexpr( aggregate_size == 3 ) - { - auto &[ a0, a1, a2 ]= agg; - return std::tie( a0, a1, a2 ); - } - else if constexpr( aggregate_size == 4 ) - { - auto &[ a0, a1, a2, a3 ]= agg; - return std::tie( a0, a1, a2, a3 ); - } - else if constexpr( aggregate_size == 5 ) - { - auto &[ a0, a1, a2, a3, a4 ]= agg; - return std::tie( a0, a1, a2, a3, a4 ); - } - else if constexpr( aggregate_size == 6 ) - { - auto &[ a0, a1, a2, a3, a4, a5 ]= agg; - return std::tie( a0, a1, a2, a3, a4, a5 ); - } - else if constexpr( aggregate_size == 7 ) - { - auto &[ a0, a1, a2, a3, a4, a5, a6 ]= agg; - return std::tie( a0, a1, a2, a3, a4, a5, a6 ); - } - else if constexpr( aggregate_size == 8 ) - { - auto &[ a0, a1, a2, a3, a4, a5, a6, a7 ]= agg; - return std::tie( a0, a1, a2, a3, a4, a5, a6, a7 ); - } - else if constexpr( aggregate_size == 9 ) - { - auto &[ a0, a1, a2, a3, a4, a5, a6, a7, a8 ]= agg; - return std::tie( a0, a1, a2, a3, a4, a5, a6, a7, a8 ); - } - else if constexpr( aggregate_size == 10 ) - { - auto &[ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 ]= agg; - return std::tie( a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 ); - } - else if constexpr( aggregate_size == 11 ) - { - auto &[ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 ]= agg; - return std::tie( a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 ); - } - else if constexpr( aggregate_size == 12 ) - { - auto &[ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11 ]= agg; - return std::tie( a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11 ); - } - else if constexpr( aggregate_size == 13 ) - { - auto &[ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 ]= agg; - return std::tie( a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 ); - } - else if constexpr( aggregate_size == 14 ) - { - auto &[ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13 ]= agg; - return std::tie( a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13 ); - } - else if constexpr( aggregate_size == 15 ) - { - auto &[ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14 ]= agg; - return std::tie( a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14 ); - } - else if constexpr( aggregate_size == 16 ) - { - auto &[ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 ]= agg; - return std::tie( a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 ); - } - // Impossible, in this case -- we would have taken the original 0 branch were this so. - else static_assert( aggregate_size == 0, "The specified aggregate has more members than `tuplizeAggregate` can handle" ); - } - - // This overload deduces the aggregate size using the initializer inspection utilities. - template< typename Aggregate > - constexpr decltype( auto ) - tuplizeAggregate( Aggregate &&agg ) - { - return tuplizeAggregate< compute_salient_members_count_v< std::decay_t< Aggregate > > >( std::forward< Aggregate >( agg ) ); - } - - template< typename Aggregate > - using aggregate_tuple_t= decay_tuple_t< std::decay_t< decltype( tuplizeAggregate( std::declval< const Aggregate & >() ) ) > >; - } + template< typename T > + constexpr std::size_t + compute_salient_members_count_impl() + { + if constexpr( SalientMembers< T > ) return T::salient_members; + else return aggregate_member_count_v< std::decay_t< T > >; } - namespace exports::tuplize_aggregate + template< typename T > + constexpr std::size_t compute_salient_members_count_v= compute_salient_members_count_impl< T >(); + + namespace exports { - using namespace detail::tuplize_aggregate::exports; + /*! + * Deconstruct an aggregate object into a tie-based tuple pointing at its members. + * + * C++17's primary new reflection-oriented introduction is Structured Binding Declarations. + * What these let one do is to introduce a set of named variables that bind to each member + * of a (raw aggregate) `struct` in turn. This leads to some very interesting forms of + * "reflection" about what a user defined type is made of. Combined with the `std::is_aggregate` + * trait function and a way to determine the number of member objects, this provides a + * powerful new way to inspect any type. + * + * Structured Binding Declarations can also be used with arrays or types which implement a subset + * of the `std::tuple` interface. Those cases are not as interesting. We've always had the + * ability to inspect arrays via templates -- simple deduction operations work for that. And + * C++11's `std::tuple`s are already inspectable by their nature and types which implement a tuple-like + * interface are also easily inspected by pre-C++17 means. + * + * The most important thing C++17 Structured Binding brings to the language is the ability to + * (at compiletime) programmatically inspect any structure's members -- to learn their types, + * and with a bit of special effort, to learn their offsets. The names of those members are + * hidden, but their types are available, as is a way to work with all of them at once. Any + * Structured Binding is sufficient to do this -- one need only give a new name for each member of + * the type. `auto &[ a, b, c, d ]= someStruct;` is all that is needed and one has already performed + * an interesting feat of rudimentary reflection on the type `someStruct`. By loading those values + * into a tuple (by reference), by code such as `std::tie( a, b, c, d )`, a programmer can provide + * an anonymized, distilled reflection of the contents of that `struct`. This said, a library function + * which can decompose any `struct` into such a tie is very useful. `tuplizeAggregate` is exactly this. + * + * This function contains a pre-built set of such decompositions for structs of various sizes. C++17 + * does not permit arbitrarily sized Structured Bindings, and so a limit had to be placed. The limit + * is fairly generous, however. If an aggregate size which is greater than the pre-build maximum is + * provided, then the compile will fail on a `static_assert` indicating this. + * + * Unfortunately, as a declaration syntax, the number of members in a `struct`'s body cannot be inferred + * through SFINAE by this means. Normally the user must explicitly provide the number of member + * variables. However, combined with a pair of C++11 features (based upon variadic templates and + * aggregate initialization syntax) we can infer the number of memmber values via a set of helper + * templates (which can also be called directly.) + * + * This kind of reflection into an aggregate type can prove very useful. Code generators for + * serialization, conversion tools, universal utility functions, and much more can all be built in + * C++17, today, using this kind of reflection! There's no need to wait for C++23 or beyond when + * static reflection is added to the language. A great deal of desired reflection use cases can be + * attained today. One just need write some code generators in terms of `std::tuple` and `std::tie`, + * then make any overloads (perhaps using ADL hooking tricks) which call `Alepha::Reflection::tuplizeAggregate` + * and pass that result to the general tuple form. For serializers and such, other techniques such as + * `boost::core::demangle( typeid( instance ).name() )` can be used to get nice names for types when + * implementing universal serializers. In fact, this can be used as a crutch for serializing more + * complicated user types (with private data and such). Those types can produce an aggregate "view" + * of what they must serialize or deserialize, and then they can hand that view off to such code + * generators. And, of cousre, this need not apply just to serialization. + * + * @param agg Aggregate instance to decompose into a `std::tie` based `std::tuple`. + * @tparam aggregate_size The number of members in the aggregate argument `agg`'s definition. + * @tparam Aggregate The type of the aggregate to decompose. + */ + // TODO: Make `aggregate_size` deduced via `Reflection::aggregate_ctor...` means. + template< std::size_t aggregate_size, typename Aggregate, typename= std::enable_if_t< not std::is_rvalue_reference_v< Aggregate > > > + constexpr decltype( auto ) + tuplizeAggregate( Aggregate &&agg ) + { + static_assert( std::is_aggregate_v< std::decay_t< Aggregate > >, "`tuplizeAggregate` only can be used on aggregates" ); + + // TODO: Generate these cases via boost preprocessor, to cut down on repetition... + if constexpr( aggregate_size == 0 ) return std::tuple{}; + else if constexpr( aggregate_size == 1 ) + { + auto &[ a0 ]= agg; + return std::tie( a0 ); + } + else if constexpr( aggregate_size == 2 ) + { + auto &[ a0, a1 ]= agg; + return std::tie( a0, a1 ); + } + else if constexpr( aggregate_size == 3 ) + { + auto &[ a0, a1, a2 ]= agg; + return std::tie( a0, a1, a2 ); + } + else if constexpr( aggregate_size == 4 ) + { + auto &[ a0, a1, a2, a3 ]= agg; + return std::tie( a0, a1, a2, a3 ); + } + else if constexpr( aggregate_size == 5 ) + { + auto &[ a0, a1, a2, a3, a4 ]= agg; + return std::tie( a0, a1, a2, a3, a4 ); + } + else if constexpr( aggregate_size == 6 ) + { + auto &[ a0, a1, a2, a3, a4, a5 ]= agg; + return std::tie( a0, a1, a2, a3, a4, a5 ); + } + else if constexpr( aggregate_size == 7 ) + { + auto &[ a0, a1, a2, a3, a4, a5, a6 ]= agg; + return std::tie( a0, a1, a2, a3, a4, a5, a6 ); + } + else if constexpr( aggregate_size == 8 ) + { + auto &[ a0, a1, a2, a3, a4, a5, a6, a7 ]= agg; + return std::tie( a0, a1, a2, a3, a4, a5, a6, a7 ); + } + else if constexpr( aggregate_size == 9 ) + { + auto &[ a0, a1, a2, a3, a4, a5, a6, a7, a8 ]= agg; + return std::tie( a0, a1, a2, a3, a4, a5, a6, a7, a8 ); + } + else if constexpr( aggregate_size == 10 ) + { + auto &[ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 ]= agg; + return std::tie( a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 ); + } + else if constexpr( aggregate_size == 11 ) + { + auto &[ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 ]= agg; + return std::tie( a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 ); + } + else if constexpr( aggregate_size == 12 ) + { + auto &[ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11 ]= agg; + return std::tie( a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11 ); + } + else if constexpr( aggregate_size == 13 ) + { + auto &[ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 ]= agg; + return std::tie( a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 ); + } + else if constexpr( aggregate_size == 14 ) + { + auto &[ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13 ]= agg; + return std::tie( a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13 ); + } + else if constexpr( aggregate_size == 15 ) + { + auto &[ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14 ]= agg; + return std::tie( a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14 ); + } + else if constexpr( aggregate_size == 16 ) + { + auto &[ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 ]= agg; + return std::tie( a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 ); + } + // Impossible, in this case -- we would have taken the original 0 branch were this so. + else static_assert( aggregate_size == 0, "The specified aggregate has more members than `tuplizeAggregate` can handle" ); + } + + // This overload deduces the aggregate size using the initializer inspection utilities. + template< typename Aggregate > + constexpr decltype( auto ) + tuplizeAggregate( Aggregate &&agg ) + { + return tuplizeAggregate< compute_salient_members_count_v< std::decay_t< Aggregate > > >( std::forward< Aggregate >( agg ) ); + } + + template< typename Aggregate > + using aggregate_tuple_t= decay_tuple_t< std::decay_t< decltype( tuplizeAggregate( std::declval< const Aggregate & >() ) ) > >; } } + +namespace Alepha::Hydrogen::Reflection::inline exports::inline tuplizeAggregate_m +{ + using namespace detail::tuplizeAggregate_m::exports; +} diff --git a/Reflection/tuplizeAggregate.test/0.cc b/Reflection/tuplizeAggregate.test/0.cc index b8d444c..9bc96f0 100644 --- a/Reflection/tuplizeAggregate.test/0.cc +++ b/Reflection/tuplizeAggregate.test/0.cc @@ -56,7 +56,7 @@ namespace static_assert( Alepha::Reflection::aggregate_empty_bases_v< instance3 > == 2 ); auto t= "test"_test <=[] { - using namespace Alepha::Reflection::detail::aggregate_members; + using namespace Alepha::Reflection::detail::aggregate_members_m; std::cout << Alepha::Reflection::aggregate_empty_bases_v< instance3 > << std::endl; static_assert( std::is_empty_v< empty1 > ); diff --git a/Testing/TableTest.h b/Testing/TableTest.h index 05d506e..81ae076 100644 --- a/Testing/TableTest.h +++ b/Testing/TableTest.h @@ -41,7 +41,7 @@ namespace Alepha::Hydrogen::Testing ::detail:: TableTest_m namespace C:: inline Colors { - using namespace testing_colors::C:: Colors; + using namespace Testing::detail::colors_m::C:: Colors; } enum class TestResult { Passed, Failed }; @@ -285,7 +285,7 @@ namespace Alepha::Hydrogen::Testing ::detail:: TableTest_m } using std::begin, std::end; - using namespace Utility::exports::evaluation_helpers; + using namespace Utility::exports::evaluation_helpers_m; template< template< typename, typename... > class Sequence, typename ... TupleArgs > auto diff --git a/Testing/TableTest.test/test.cc b/Testing/TableTest.test/test.cc index fef4dd0..057f7c6 100644 --- a/Testing/TableTest.test/test.cc +++ b/Testing/TableTest.test/test.cc @@ -8,7 +8,7 @@ namespace { namespace UnitTest= Alepha::Testing::exports; - using namespace Alepha::Utility::exports::evaluation_helpers; + using namespace Alepha::Utility::exports::evaluation_helpers_m; using namespace UnitTest::literals; using UnitTest::TableTest; diff --git a/Testing/TableTest.test/test2.cc b/Testing/TableTest.test/test2.cc index 8a11d68..80b90a7 100644 --- a/Testing/TableTest.test/test2.cc +++ b/Testing/TableTest.test/test2.cc @@ -14,7 +14,7 @@ static_assert( __cplusplus > 2020'99 ); namespace { using namespace Alepha::Testing::exports; - using namespace Alepha::Utility::exports::evaluation_helpers; + using namespace Alepha::Utility::exports::evaluation_helpers_m; int add( int a, int b ) diff --git a/Testing/colors.h b/Testing/colors.h index af9caac..4d7d492 100644 --- a/Testing/colors.h +++ b/Testing/colors.h @@ -4,7 +4,7 @@ static_assert( __cplusplus > 2020'99 ); #include -namespace Alepha::Hydrogen::Testing ::detail:: testing_colors +namespace Alepha::Hydrogen::Testing ::detail:: colors_m { namespace C { diff --git a/Testing/test.cc b/Testing/test.cc index 9fe1555..f00a8e5 100644 --- a/Testing/test.cc +++ b/Testing/test.cc @@ -2,7 +2,7 @@ static_assert( __cplusplus > 2020'99 ); #include "test.h" -namespace Alepha::Hydrogen::Testing::detail::testing +namespace Alepha::Hydrogen::Testing ::detail:: test_m { StaticValue< std::vector< std::tuple< std::string, bool, std::function< void() > > > > registry; diff --git a/Testing/test.h b/Testing/test.h index 75f4838..7124949 100644 --- a/Testing/test.h +++ b/Testing/test.h @@ -23,9 +23,9 @@ static_assert( __cplusplus > 2020'99 ); namespace Alepha::Hydrogen::Testing { - inline namespace exports { inline namespace testing {} } + inline namespace exports { inline namespace test_m {} } - namespace detail::testing + namespace detail::test_m { inline namespace exports {} @@ -35,11 +35,11 @@ namespace Alepha::Hydrogen::Testing const bool debugTestRegistration= false or C::debug; const bool debugTestRun= false or C::debug; - using namespace testing_colors::C::Colors; + using namespace detail::colors_m::C::Colors; } using namespace std::literals::string_literals; - using namespace Utility::exports::evaluation_helpers; + using namespace Utility::exports::evaluation_helpers_m; using namespace Utility::exports::StaticValue_m; struct TestName @@ -167,13 +167,13 @@ namespace Alepha::Hydrogen::Testing } } - namespace exports::testing + namespace exports::test_m { - using namespace detail::testing::exports; + using namespace detail::test_m::exports; } namespace exports::inline literals::inline test_literals { - using namespace detail::testing::exports::literals; + using namespace detail::test_m::exports::literals; } } diff --git a/Thread.cc b/Thread.cc index bb05a54..427950f 100644 --- a/Thread.cc +++ b/Thread.cc @@ -12,7 +12,7 @@ static_assert( __cplusplus > 2020'99 ); #include "error.h" -namespace Alepha::Hydrogen::detail::Thread_m +namespace Alepha::Hydrogen ::detail:: Thread_m { namespace { diff --git a/Utility/evaluation_helpers.h b/Utility/evaluation_helpers.h index bf0b94b..47643e6 100644 --- a/Utility/evaluation_helpers.h +++ b/Utility/evaluation_helpers.h @@ -7,7 +7,7 @@ static_assert( __cplusplus > 2020'99 ); #include #include -namespace Alepha::Hydrogen::Utility ::detail:: evaluation_helpers +namespace Alepha::Hydrogen::Utility ::detail:: evaluation_helpers_m { inline namespace exports { @@ -165,7 +165,7 @@ namespace Alepha::Hydrogen::Utility ::detail:: evaluation_helpers } } -namespace Alepha::Hydrogen::Utility::inline exports::inline evaluation_helpers +namespace Alepha::Hydrogen::Utility::inline exports::inline evaluation_helpers_m { - using namespace detail::evaluation_helpers::exports; + using namespace detail::evaluation_helpers_m::exports; } diff --git a/Utility/fancyTypeName.cc b/Utility/fancyTypeName.cc index 2a10c6b..1ec6681 100644 --- a/Utility/fancyTypeName.cc +++ b/Utility/fancyTypeName.cc @@ -4,7 +4,7 @@ static_assert( __cplusplus > 2020'99 ); #include -namespace Alepha::Hydrogen::Utility::detail::fancyTypeName_m +namespace Alepha::Hydrogen::Utility ::detail:: fancyTypeName_m { std::string exports::fancyTypeName( const std::type_index idx ) diff --git a/example.cc b/example.cc index f7cf926..9ae84fc 100644 --- a/example.cc +++ b/example.cc @@ -9,7 +9,7 @@ namespace using namespace Alepha::literals::option_literals; using namespace std::literals::string_literals; - using namespace Alepha::Utility::exports::evaluation_helpers; + using namespace Alepha::Utility::exports::evaluation_helpers_m; int optionA= 42; std::optional< std::string > optionB; diff --git a/tuplize_args.test/0.cc b/tuplize_args.test/0.cc index d5d5cb1..132d830 100644 --- a/tuplize_args.test/0.cc +++ b/tuplize_args.test/0.cc @@ -8,7 +8,7 @@ static auto init= Alepha::Utility::enroll <=[] { using namespace Alepha::Testing::exports; - using namespace Alepha::Utility::exports::evaluation_helpers; + using namespace Alepha::Utility::exports::evaluation_helpers_m; "A basic tuplization example"_test <=TableTest < diff --git a/types.h b/types.h index f1051c6..475da9f 100644 --- a/types.h +++ b/types.h @@ -4,21 +4,16 @@ static_assert( __cplusplus > 2020'99 ); #include -namespace Alepha::Hydrogen +namespace Alepha::Hydrogen ::detail:: types_m { - inline namespace exports { inline namespace types_m {} } - - namespace detail::types_m + inline namespace exports { - inline namespace exports - { - using argvec_t= const char *const []; - using argcnt_t= int; - } - } - - namespace exports::types_m - { - using namespace detail::types_m::exports; + using argvec_t= const char *const []; + using argcnt_t= int; } } + +namespace Alepha::Hydrogen::inline exports::inline types_m +{ + using namespace detail::types_m::exports; +} diff --git a/word_wrap.cc b/word_wrap.cc index 4f6bf5c..628997a 100644 --- a/word_wrap.cc +++ b/word_wrap.cc @@ -16,7 +16,7 @@ namespace Alepha::Hydrogen ::detail:: word_wrap_m { namespace { - using namespace Utility::exports::evaluation_helpers; + using namespace Utility::exports::evaluation_helpers_m; // Returns the number of chars in the line just written to. std::size_t