std :: remove_reference解释了吗? [英] std::remove_reference explained?
问题描述
我看到了 std :: remove_reference
如下
I saw possible implementations for std::remove_reference
as below
template< class T > struct remove_reference {typedef T type;};
template< class T > struct remove_reference<T&> {typedef T type;};
template< class T > struct remove_reference<T&&> {typedef T type;};
为什么对 lvalue
和 rvalue参考
有专门的说明?通用模板本身不足以删除参考吗?我在这里感到困惑,因为在 T&
或 T&&
专业化中,如果我尝试使用 :: type
,我仍然应该得到 T&
或 T&&
正确吗?
Why is it that there are specializations for lvalue
and rvalue reference
? Won't the general template itself be sufficient and remove the reference? I'm confused here because in the T&
or T&&
specialization if I try to use ::type
I should still get T&
or T&&
respectively right?
您能否解释一下,为什么我们在移动时强制转换为 remove_reference< t> :: type&&
?(是因为参数已命名,所以将其视为move函数中的左值?).
Could you explain how, why we cast to remove_reference<t>::type&&
in move? (is it because that the parameter is named so it will be treated as an lvalue inside the move function?).
此外,您能指出一种找出并打印出什么类型的方法的方法吗?例如,如果其类型为 int
的 rvalue
,那么我应该能够打印出已通过 int&&
的信息?(我一直在使用 std :: is_same
进行手动检查.)
Also, could you point out a way whereby I can find out and print what the type is? for e.g if its an rvalue
of type int
then I should be able to print out that int&&
was passed? (I've been using std::is_same
to check but manually.)
谢谢您的时间.
推荐答案
为什么左值和右值引用有专门的专业知识?
why is it that there are specializations for lvalue and rvalue reference?
如果仅存在主模板,则执行以下操作:
If only the primary template existed, then doing:
remove_reference<int&>::type
会给你:
int&
并且正在做
remove_reference<int&&>::type
会给你:
int&&
这不是您想要的.左值引用和右值引用的特殊化允许从传递的类型参数中分别剥离&
和&
.
Which is not what you want. The specializations for lvalue references and rvalue references allow stripping the &
and the &&
, respectively, from the type argument you pass.
例如,如果您正在做
remove_reference<int&&>
类型 int&&
将匹配由 T&&
专业化指定的模式,其中 T
为 int
.由于专业化将类型别名 type
定义为 T
(在本例中为 int
),因此请执行以下操作:
The type int&&
will match the pattern specified by the T&&
specialization, with T
being int
. Since the specialization defines the type alias type
to be T
(in this case, int
), doing:
remove_reference<int&&>::type
会给你 int
.
您能解释为什么,为什么我们在
move
中强制转换为remove_reference< t> :: type&
吗?
这是因为如果 move()
的定义如下:
That's because if move()
were defined as follows:
template<typename T>
T&& move(T&& t) { ... }
// ^^^
// Resolves to X& if T is X& (which is the case if the input has type X
// and is an lvalue)
然后,如果 move()
的参数是 X
类型的左值,则返回类型将为 X&
(这就是-称为通用引用").我们要确保返回类型始终是右值引用.
Then the return type will be X&
if the argument of move()
is an lvalue of type X
(that's how so-called "universal references"). We want to make sure that the return type is always an rvalue reference.
move()
的目的是使您返回右值,无论您在输入中传递了什么.由于函数调用的函数的返回类型是右值引用是右值,因此我们确实希望 move()
始终返回右值引用.
The purpose of move()
is to give you back an rvalue, no matter what you pass in input. Since a function call for a function whose return type is an rvalue reference is an rvalue, we really want move()
to always return an rvalue reference.
这就是为什么我们要执行 remove_reference< T> :: type&&
,因为始终保证将&&
附加到非引用类型可以保证生成一个右值引用类型.
That's why we do remove_reference<T>::type&&
, because appending &&
to a non-reference type is always guaranteed to yield an rvalue reference type.
您还能指出一种方法,让我找出并打印出类型吗?
Also could you point out a way whereby I can find out and print what the type is?
我不确定您在这里所说的打印"是什么意思.我不知道将类型的名称转换为字符串的便携式方法(无论如何获取该类型).
I'm not sure what you mean by "print" here. There is no portable way I know of converting the name of a type to a string (no matter how you obtain that type).
另一方面,如果您的目标是确保传递了右值,则可以使用静态断言,如下所示:
If your goal is to make sure that an rvalue was passed, on the other hand, you could use a static assertion like so:
#include <type_traits>
template<typename T>
void foo(T&&)
{
static_assert(!std::is_reference<T>::value, "Error: lvalue was passed!");
// ...
}
这取决于以下事实:当传递类型为 X
的左值时,将推导出 T
为 X&
.
Which relies on the fact that when an lvalue of type X
is being passed, T
will be deduced to be X&
.
如果只想产生替换失败,也可以使用等效的SFINAE约束:
You could also use an equivalent SFINAE-constraint, if you only want to produce a substitution failure:
#include <type_traits>
template<typename T, typename std::enable_if<
!std::is_reference<T>::value>::type* = nullptr>
void foo(T&&)
{
// ...
}
这篇关于std :: remove_reference解释了吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!