Created
July 24, 2019 21:27
-
-
Save B1Z0N/abfe5740d19ecb561dc80416561e737d to your computer and use it in GitHub Desktop.
Code for generation of predicate traits
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Code for generation of predicate traits | |
// compile with g++ -std=c++17 ... | |
#include <utility> | |
#include <vector> | |
#include <iostream> | |
// ***************IMPLEMENTATION*************** | |
// checks whether F( args... ) is true | |
template <typename F, typename... Args, | |
typename = decltype( std::declval<F>()( std::declval<Args&&>( )... ) )> | |
std::true_type is_valid_impl( void* ); | |
// if not true return false_type | |
template <typename F, typename... Args> | |
std::false_type is_valid_impl( ... ); | |
// trait factory itself | |
inline constexpr auto IsValid { | |
[ ] ( auto f ) { | |
return [ ] ( auto&&... args ) { | |
return decltype( | |
is_valid_impl<decltype( f ), | |
decltype( args )&&... >( nullptr ) | |
) { }; | |
}; | |
} | |
}; | |
// helper to represent type as a value | |
template <typename T> | |
struct TypeT | |
{ | |
using Type = T; | |
}; | |
template <typename T> | |
constexpr auto type = TypeT<T> { }; | |
// helper to unwrap value from type | |
template <typename T> | |
T ValueT( TypeT<T> ); | |
// ******************USAGE****************** | |
struct Data | |
{ | |
using TypeMember = Data; | |
int DataMember; | |
void Method(); | |
}; | |
constexpr auto IsDefaultConstructible { | |
IsValid( | |
[ ] ( auto&& x ) -> decltype( ( void ) decltype( ValueT( x ) ) { } ) { } | |
) | |
}; | |
constexpr auto HasMethod { | |
IsValid( | |
[ ] ( auto&& x ) -> decltype( ( void ) ValueT( x ).Method() ) { } | |
) | |
}; | |
constexpr auto HasSizeMethod { | |
IsValid( | |
[ ] ( auto&& x ) -> decltype( ( void ) ValueT( x ).size() ) { } | |
) | |
}; | |
constexpr auto HasDataMember { | |
IsValid( | |
[ ] ( auto&& x ) -> decltype( ( void ) ValueT( x ).DataMember ) { } | |
) | |
}; | |
// type member can't be accesed through pointer or reference types | |
// so we do `decay` | |
constexpr auto HasTypeMember { | |
IsValid( | |
[ ] ( auto&& x ) -> typename std::decay<decltype( ValueT( x ) )>::type::TypeMember { } | |
) | |
}; | |
template <typename T> | |
void check_traits( ) | |
{ | |
std::cout << std::boolalpha; | |
std::cout << "Is default constructible? - " << IsDefaultConstructible( type<T> ) << '\n'; | |
std::cout << "Has method named 'Method'? - " << HasMethod( type<T> ) << '\n'; | |
std::cout << "Has data member named 'DataMember'? - " << HasDataMember( type<T> ) << '\n'; | |
std::cout << "Has type member named 'TypeMember'? - " << HasTypeMember( type<T> ) << '\n'; | |
std::cout << "Has method 'size()'? - " << HasSizeMethod( type<T> ) << '\n'; | |
} | |
int main() | |
{ | |
std::cout << "\nstd::vector:\n"; | |
check_traits<std::vector<int>>( ); | |
std::cout << "\nint:\n"; | |
check_traits<int>( ); | |
std::cout << "\nint&:\n"; | |
check_traits<int&>( ); | |
std::cout << "\nData:\n"; | |
check_traits<Data>( ); | |
std::cout << "\nData&:\n"; | |
check_traits<Data&>( ); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment