C ++:如何为lvalue和rvalue特化不同

时间:2015-02-14 09:23:04

标签: c++ templates

我想为具有特定标记(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,但是怎么样?

1 个答案:

答案 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