diff --git a/Capabilities.h b/Capabilities.h index b926c10..ad7944d 100644 --- a/Capabilities.h +++ b/Capabilities.h @@ -65,7 +65,7 @@ namespace Alepha::Hydrogen struct higher_kind_tuple {}; template< typename Cap, typename ... Caps > - constexpr bool + consteval bool has_cap_in_capability_base( const Meta::type_value< Capabilities< Caps... > > &, Meta::type_value< Cap > cap ) { Meta::Container::vector< Caps... > types; @@ -81,7 +81,7 @@ namespace Alepha::Hydrogen } template< typename Cap, typename ... TParams > - constexpr bool + consteval bool has_cap( const Meta::Container::vector< TParams... > &types, Meta::type_value< Cap > cap ) { bool rv= 0; diff --git a/IOStreams/IStreamable.test/0.cc b/IOStreams/IStreamable.test/0.cc index 440486a..a1d7096 100644 --- a/IOStreams/IStreamable.test/0.cc +++ b/IOStreams/IStreamable.test/0.cc @@ -9,25 +9,22 @@ static_assert( __cplusplus > 2020'00 ); #include +#include + namespace { - template< typename= Alepha::Capabilities< Alepha::auto_comparable, Alepha::IOStreams::IStreamable > > + template< typename= Alepha::Capabilities< Alepha::auto_comparable, Alepha::IOStreams::IStreamable, Alepha::IOStreams::OStreamable > > struct Agg_core { int x; int y; int z; - - friend std::ostream & - operator << ( std::ostream &os, const Agg_core &agg ) - { - return os << "{ " << agg.x << ", " << agg.y << ", " << agg.z << " }"; - } }; using Agg= Agg_core<>; static_assert( Alepha::Aggregate< Agg > ); static_assert( Alepha::Capability< Agg, Alepha::IOStreams::IStreamable > ); + static_assert( Alepha::Capability< Agg, Alepha::IOStreams::OStreamable > ); } diff --git a/IOStreams/OStreamable.h b/IOStreams/OStreamable.h new file mode 100644 index 0000000..fe4789c --- /dev/null +++ b/IOStreams/OStreamable.h @@ -0,0 +1,60 @@ +static_assert( __cplusplus > 2020'00 ); + +#pragma once + +#include + +#include + +#include +#include +#include +#include + +#include + +namespace Alepha::Hydrogen::IOStreams ::detail:: ostreamable_module +{ + inline namespace exports + { + struct OStreamable {}; + } + + template< typename T > + concept OStreamableAggregate= Aggregate< T > + // For now, this part seems to have problems, since the `has_capability` function + // is either broken... or gcc has a bug which prevents it from functioning + // correctly. + // + // Therefore, we just allow the aggregate case, for the moment. Which is the + // most common case, anyhow. + //and Capability< T, OStreamable > + ; + + template< OStreamableAggregate Agg > + std::ostream & + operator << ( std::ostream &os, Agg &ostreamable ) + { + const auto decomposed= Alepha::Reflection::tuplizeAggregate( ostreamable ); + //static_assert( Capability< Agg, exports::OStreamable > ); + + bool first= true; + // TODO: Consider the lens system here... but the basic use case seems to be for + // aggregates, so we'll go with this simple case for now... + tuple_for_each( decomposed ) <=[&]( const auto &element ) + { + if( not first ) os << '\t'; + first= false; + os << element; + }; + os << '\n'; + + return os; + } +} + +namespace Alepha::Hydrogen::IOStreams::inline exports::inline ostreamable_module +{ + using namespace detail::ostreamable_module::exports; +} +