add_lvalue_reference_t<T> 和 T& 之间的区别

Posted

技术标签:

【中文标题】add_lvalue_reference_t<T> 和 T& 之间的区别【英文标题】:Difference between add_lvalue_reference_t<T> and T& 【发布时间】:2015-08-21 18:37:25 【问题描述】:

假设您有一个模板参数T

两者有什么区别

add_cv_t&lt;T&gt;const volatile T add_const_t&lt;T&gt;const T add_volatile_t&lt;T&gt;volatile T add_lvalue_reference_t&lt;T&gt;T&amp; add_rvalue_reference_t&lt;T&gt;T&amp;&amp; add_pointer_t&lt;T&gt;T*?

例如,为什么我应该使用add_rvalue_reference_t&lt;T&gt; 而不是T&amp;&amp;。什么时候选哪个有什么规定吗?

【问题讨论】:

【参考方案1】:
add_cv_t&lt;T&gt;const volatile T add_const_t&lt;T&gt;const T add_volatile_t&lt;T&gt;volatile T

没有区别;例如add_const&lt;T&gt;::type 的定义就是T const

add_lvalue_reference_t&lt;T&gt;T&amp; add_rvalue_reference_t&lt;T&gt;T&amp;&amp;

T&amp;T&amp;&amp;Tcv void 时格式不正确,但这些模板格式正确,只是返回原始类型。

add_pointer_t&lt;T&gt;T*?

add_pointer_t&lt;T&gt; 等价于std::remove_reference&lt;T&gt;::type*。也就是说,如果T 是一个引用类型,它会给出一个指向被引用类型的指针。另一方面,T* 格式错误,因为您不能拥有指向引用的指针。

你应该使用哪个?

一般情况下,可以使用别名模板来防止T的扣除。当然,这意味着如果你想扣除,你应该避免它们。 别名模板可用作将类型转换作为参数的模板的模板模板参数。 在行为上与T* 等替代模板不同的别名模板在通用代码中很有用,因为它们“做正确的事”。例如,如果T 是从T&amp;&amp; 类型的参数推导出来的,那么当参数是左值时T* 会做错事,因为它试图声明指向左值引用的指针。但是std::add_pointer_t&lt;T&gt; 会给出一个指向参数实际类型的指针。

【讨论】:

【参考方案2】:

根据我在 STL 源码中看到的:

add_cv_t&lt;T&gt;const volatile T- 没有区别

add_const_t&lt;T&gt;const T - 没有区别

add_volatile_t&lt;T&gt;volatile T - 没有区别

add_lvalue_reference_t&lt;T&gt;T&amp; - 例如,如果 T 是不可引用类型 void,则存在差异。 add_lvalue_reference_t&lt;void&gt;::type = voidvoid&amp; = 编译时错误

add_rvalue_reference_t&lt;T&gt;T&amp;&amp; - 同上

add_pointer_t&lt;T&gt;T* - T 是引用时的区别,因为没有指向引用的指针。 add_pointer_t&lt;T&gt; 等价于std::remove_reference&lt;T&gt;::type*

【讨论】:

有趣,为什么要否决这个答案? 编译时错误不确定。在某些实现中不会发生错误【参考方案3】:

在大多数情况下,std::add_rvalue_reference_t&lt;T&gt; 等同于 T&amp;&amp;。但是,reference collapsing rules 和 the-rules-that-dictate-which-types-are-referenceable 如果不加以考虑,可能会使您的代码行为不端。

但是,由于T 是不可引用的类型,在某些情况下type 静态成员类型会有所不同。例如std::add_rvalue_reference_t&lt;void&gt;解析为void,并且(以你提到的另一个模板为例)std::add_pointer_t&lt;T&amp;&gt;解析为T*(如果你想调用混乱,所需的仪式是std::add_pointer_t&lt;std::add_rvalue_reference_t&lt;void&gt;&gt;:))

就用途而言,它可以作为模板模板参数来做一些时髦的黑魔法。无论如何,std::is_rvalue_reference_t&lt;T&gt;std::remove_reference_t&lt;T&gt; 之类的东西通常在操作类型的引用属性时更常用。

【讨论】:

最好说“可能”而不是断言可能(不知何故)不是这样的事情。这背后的要点和“他/她的意见”是 OP 没有具体说明他/她在做什么(或者更确切地说,为什么)。是简单的理论吗?或者更确切地说,正如我所说的,“黑魔法”?我们不知道,参考折叠规则会在很大程度上影响他/她的代码是否行为不端(如果不考虑的话)。 顺便说一句,我再次编辑。在之前的编辑中,第一段变得毫无意义,所以@Barry 有他的观点。 别名模板如何影响参考折叠? 您可能的意思是“引用折叠如何影响别名模板?”,它本身应该改写为“引用折叠如何影响模板?”。嗯,答案有点复杂,应该在另一个问题上解决。

以上是关于add_lvalue_reference_t<T> 和 T& 之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

WEB开发经验点滴

X-005 FriendlyARM tiny4412 uboot移植之时钟初始化

X-004 FriendlyARM tiny4412 uboot移植之点亮指路灯

X-003 FriendlyARM tiny4412 uboot移植之添加相应目录文件

X-007 FriendlyARM tiny4412 u-boot移植之内存初始化

X-009 FriendlyARM tiny4412 uboot移植之SD Card用起来Kernel boot起来