我想为具有特定标记(is_gpio_class)的类型创建一个装饰器,该标记对于rvalues(必须复制)和lvalues(存储引用)实现不同。为了避免提及类型,我使用了一个返回装饰类型的功能模板。
#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 );
}
当该功能具有&amp;参数,但要区分rval和lval我认为我必须把它作为&amp;&amp;,然后以某种方式匹配lvalue和rvalue,但是怎么样?
答案 0 :(得分:2)
您只需要从P
的{{1}}来电中删除推断的invert_x
中的引用。使用std::remove_reference_t
:
invert
编辑:要支持rvalue和左值重载,请使用这样的tag-dispatching:
template< typename P >
invert_x< P > invert( P && pin )
{
return invert_x< std::remove_reference_t<P> >( pin );
}
为template< typename P >
invert_x< P > invert( P && pin )
{
return invert_x< std::remove_reference_t<P> >( pin,
std::is_lvalue_reference<P&&>());
}
的构造函数提供这些重载:
invert_x