add_lvalue_reference_t <t>与T&amp;

时间:2015-08-21 18:37:25

标签: c++ templates c++11 generic-programming

假设您有一个模板参数T

之间有什么区别
  • add_cv_t<T>const volatile T
  • add_const_t<T>const T
  • add_volatile_t<T>volatile T
  • add_lvalue_reference_t<T>T&
  • add_rvalue_reference_t<T>T&&
  • add_pointer_t<T>T*

为什么我应该使用add_rvalue_reference_t<T>代替T&&。有什么规则可供选择吗?

3 个答案:

答案 0 :(得分:13)

  
      
  • add_cv_t<T>const volatile T
  •   
  • add_const_t<T>const T
  •   
  • add_volatile_t<T>volatile T
  •   

没有区别;例如,add_const<T>::type的定义仅为T const

  
      
  • add_lvalue_reference_t<T>T&
  •   
  • add_rvalue_reference_t<T>T&&
  •   
T& cv T&&时,

Tvoid格式不正确,但这些模板格式正确,只是给出了原型返回。

  
      
  • add_pointer_t<T>T*
  •   

add_pointer_t<T>相当于std::remove_reference<T>::type*。也就是说,如果T是引用类型,则它会提供指向引用类型的指针。另一方面,由于你没有指向引用的指针,T*将是格式错误的。

你应该使用哪种?

  • 通常,别名模板可用于防止扣除T。当然,这意味着如果你想要扣除,你应该避免它们。
  • 别名模板可用作模板的模板模板参数,该模板将类型转换作为参数。
  • T*等替代方案不同的别名模板在通用代码中非常有用,因为它们可以做正确的事情&#34;。例如,如果从T类型的参数推导出T&&,那么当参数是左值时,T*会做错误的事情,因为它试图声明一个指向左值参考的指针。但是std::add_pointer_t<T>会给出一个指向参数实际类型的指针。

答案 1 :(得分:3)

根据我在STL来源中看到的内容:

add_cv_t<T>const volatile T - 没有区别

add_const_t<T>const T - 没有区别

add_volatile_t<T>volatile T - 没有区别

add_lvalue_reference_t<T>T& - 例如,如果T是非可引用类型void,则存在差异。 add_lvalue_reference_t<void>::type = voidvoid& =编译时错误

add_rvalue_reference_t<T>T&& - 与上述相同

add_pointer_t<T>T* - T是引用时的差异,因为没有指向引用的指针。 add_pointer_t<T>相当于std::remove_reference<T>::type*

答案 2 :(得分:0)

在大多数情况下,std::add_rvalue_reference_t<T>相当于T&&。但是,如果不考虑,reference collapsing rules和那些规定哪些类型可引用的规则可能会使您的代码行为异常。

但是,由于type是不可引用的类型,因此T静态成员类型会有所不同。例如std::add_rvalue_reference_t<void>解析为void,并且(以您提到的另一个模板为例)std::add_pointer_t<T&>解析为T*(如果您想调用混乱,则所需的仪式是std::add_pointer_t<std::add_rvalue_reference_t<void>>:))

尊重使用,它可以用作模板模板参数来做一些时髦的黑魔法。无论如何,在操作类型的引用属性时,std::is_rvalue_reference_t<T>std::remove_reference_t<T>之类的东西通常更常用。