Skip to content

Instantly share code, notes, and snippets.

@B1Z0N
Created July 24, 2019 21:27
Show Gist options
  • Save B1Z0N/abfe5740d19ecb561dc80416561e737d to your computer and use it in GitHub Desktop.
Save B1Z0N/abfe5740d19ecb561dc80416561e737d to your computer and use it in GitHub Desktop.
Code for generation of predicate traits
// 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