From 2bbb612df154e23e8af0d194bf287892e420af30 Mon Sep 17 00:00:00 2001 From: ADAM David Alan Martin Date: Sat, 3 Jul 2021 01:21:48 -0400 Subject: [PATCH] A few more meta programming bits. --- Meta/is_streamable.h | 58 ++++++++++++++++++++++++++++++++++++++++++++ Meta/is_tuple.h | 33 +++++++++++++++++++++++++ Meta/test.cc | 8 ++++++ Meta/tuple_decay.h | 36 +++++++++++++++++++++++++++ Stud/type_traits.h | 45 ++++++++++++++++++++++++++++++++++ 5 files changed, 180 insertions(+) create mode 100644 Meta/is_streamable.h create mode 100644 Meta/is_tuple.h create mode 100644 Meta/tuple_decay.h create mode 100644 Stud/type_traits.h diff --git a/Meta/is_streamable.h b/Meta/is_streamable.h new file mode 100644 index 0000000..488aeae --- /dev/null +++ b/Meta/is_streamable.h @@ -0,0 +1,58 @@ +static_assert( __cplusplus > 201700, "C++17 Required" ); + +#pragma once + +#include + +#include + +namespace Alepha::Hydrogen::Meta +{ + inline namespace exports { inline namespace type_traits {} } + + namespace detail::type_traits::is_streamable + { + inline namespace exports {} + + namespace impl + { + template< typename T, typename= void > + struct is_istreamable : std::false_type {}; + + template< typename T > + struct is_istreamable< T, std::void_t< decltype( std::declval< std::istream & >() >> std::declval< T & >() ) > > : std::true_type {}; + + template< typename T, typename= void > + struct is_ostreamable : std::false_type {}; + + template< typename T > + struct is_ostreamable< T, std::void_t< decltype( std::declval< std::ostream & >() << std::declval< T & >() ) > > : std::true_type {}; + } + + namespace exports + { + template< typename T > + constexpr bool is_istreamable_v= impl::is_istreamable< T >::value; + + template< typename T > + constexpr bool is_ostreamable_v= impl::is_ostreamable< T >::value; + + template< typename T > + constexpr bool is_streamable_v= is_istreamable_v< T > and is_ostreamable_v< T >; + + template< typename T > + struct is_istreamable : std::bool_constant< is_istreamable_v< T > > {}; + + template< typename T > + struct is_ostreamable : std::bool_constant< is_ostreamable_v< T > > {}; + + template< typename T > + struct is_streamable : std::bool_constant< is_streamable_v< T > > {}; + } + } + + namespace exports::type_traits + { + using namespace detail::type_traits::is_streamable::exports; + } +} diff --git a/Meta/is_tuple.h b/Meta/is_tuple.h new file mode 100644 index 0000000..2fc3aeb --- /dev/null +++ b/Meta/is_tuple.h @@ -0,0 +1,33 @@ +static_assert( __cplusplus > 201700, "C++17 Required" ); + +#pragma once + +#include + +#include +#include + +namespace Alepha::Hydrogen::Meta +{ + inline namespace exports { inline namespace type_traits {} } + + namespace detail::type_traits::is_tuple + { + inline namespace exports + { + template< typename T > + struct is_tuple : std::false_type {}; + + template< typename ... Args > + struct is_tuple< std::tuple< Args... > > : std::true_type {}; + + template< typename T > + constexpr bool is_tuple_v= is_tuple< T >::value; + } + } + + namespace exports::type_traits + { + using namespace detail::type_traits::is_tuple::exports; + } +} diff --git a/Meta/test.cc b/Meta/test.cc index 519f2b0..6107174 100644 --- a/Meta/test.cc +++ b/Meta/test.cc @@ -2,6 +2,8 @@ static_assert( __cplusplus > 201700, "C++17 Required" ); #include +#include + #include #include @@ -106,6 +108,12 @@ namespace static_assert( not Alepha::Meta::is_string_v< std::forward_list< std::string > > ); static_assert( not Alepha::Meta::is_string_v< std::deque< std::string > > ); }; + + "meta.streams"_test <=[] + { + static_assert( Alepha::Meta::is_streamable_v< int > ); + static_assert( not Alepha::Meta::is_streamable_v< void > ); + }; }; } diff --git a/Meta/tuple_decay.h b/Meta/tuple_decay.h new file mode 100644 index 0000000..806a7d0 --- /dev/null +++ b/Meta/tuple_decay.h @@ -0,0 +1,36 @@ +static_assert( __cplusplus > 201700, "C++17 Required" ); + +#pragma once + +#include + +#include + +#include + +namespace Alepha::Hydrogen::Meta +{ + inline namespace exports { inline namespace type_traits {} } + + namespace detail::type_traits::tuple_decay + { + inline namespace exports + { + template< typename T > struct tuple_decay; + + template< typename ... Args > + struct tuple_decay< std::tuple< T, Args... > > + { + using type= std::tuple< Stud::decay_t< Args >... >; + }; + + template< typename T > + using tuple_decay_t= typename tuple_decay< T >::type; + } + } + + namespace exports::type_traits + { + using namespace detail::type_traits::tuple_decay; + } +} diff --git a/Stud/type_traits.h b/Stud/type_traits.h new file mode 100644 index 0000000..b173980 --- /dev/null +++ b/Stud/type_traits.h @@ -0,0 +1,45 @@ +static_assert( __cplusplus > 201700, "C++17 Required" ); + +#pragma once + +#include + +#include + +namespace Alepha::Hydrogen::Stud +{ + inline namespace exports { inline namespace type_traits {} } + + namespace detail::type_traits + { + inline namespace exports + { + inline namespace + template< typename T > + struct type_identity + { + using type= T; + }; + + template< typename T > + using type_identity_t= typename type_identity< T >::type; + + using std::remove_const; + using std::remove_const_t; + + using std::decay; + using std::decay_t; + + using std::is_same; + using std::is_same_v; + + using std::enable_if; + using std::enable_if_t; + } + } + + namespace exports::type_traits + { + using namespace detail::type_traits::exports; + } +}