I want to make a decorator for types that have a certain tag (is_gpio_class) that is implemented differently for rvalues (must make a copy) and lvalues (stores a reference). To avoid having to mention the type I use a funtion template that returns the decorated type.
#include <type_traits>
template< typename T > struct always_false : std::false_type {};
// type with the tag to indicate that it is suitable
struct gpio_class {
typedef void is_gpio_class;
};
// fallback match gives an error
template< class P, class dummy = void >
struct invert_x {
static_assert( always_false< P >::value, "no match" );
};
// this should match an lvalue
template< class P >
struct invert_x< P, typename P::is_gpio_class > : public gpio_class {
constexpr invert_x( P & pin ) {}
};
// 'factory' function that dispatches to the correct specialization
template< typename P >
invert_x< P > invert( P && pin ){ return invert_x< P >( pin ); }
int main(){
gpio_class pin4;
// this works
auto led0 = invert_x< gpio_class>( pin4 );
// but this does not match the specialization
auto led1 = invert( pin4 );
}
This works when the function has a & parameter, but to distinguish between rval and lval I think I must pas it as &&, and then somehow match differently for lvalue and rvalue, but how?