Suppose you have a family of type-unrelated classes implementing a common concept by means of a given method returning a value:
class A { public: int val() const
The currently highest voted answer invokes undefined behavior in some cases, so I will give an alternative answer.
We start with some boilerplate machinery:
template struct type_sink { typedef void type; }
template using TypeSink = typename type_sink::type;
Then a has_val
traits class:
template
struct has_val : std::false_type;
template
struct has_val().val()) > > : std::true_type;
We can then use tag dispatching to solve your problem:
template
int val_of_internal( T const& t, std::true_type /* has_val */ ) {
return t.val();
}
template
int val_of_internal( T const& t, std::false_type /* has_val */ ) {
return 0;
}
template
int val_of( T const& t ) {
return val_of_internal( t, has_val() );
}
If you find writing has_val
tiresome and prefer macros, here is a set of macros that write the has_val
for you:
#define EXPRESSION_IS_VALID_FOR_TYPE_T_TRAIT( TRAIT_NAME, ... ) \
template \
struct TRAIT_NAME : std::false_type {}; \
template \
struct TRAIT_NAME< T, TypeSink< decltype( __VA_ARGS__ ) > >: std::true_type {}
#define HAS_NULLARY_METHOD_TRAIT(TRAIT_NAME, METHOD_NAME) \
EXPRESSION_IS_VALID_FOR_TYPE_T_TRAIT( TRAIT_NAME, std::declval().METHOD_NAME() )
Now we can write this:
HAS_NULLARY_METHOD_TRAIT( has_val, val );
but I do not know if it is worth it.