简体   繁体   English

std::remove_reference 解释了吗?

[英]std::remove_reference explained?

I saw possible implementations for std::remove_reference as below我看到了std::remove_reference可能实现如下

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;};   

Why is it that there are specializations for lvalue and rvalue reference ?为什么有lvaluervalue 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?我在这里很困惑,因为在T&T&&专业化中,如果我尝试使用::type我仍然应该分别获得T&T&&对吗?

Could you explain how, why we cast to remove_reference<t>::type&& in move?你能解释一下为什么我们在移动中转换为remove_reference<t>::type&&吗? (is it because that the parameter is named so it will be treated as an lvalue inside the move function?). (是不是因为参数被命名,所以它将被视为移动函数内的左值?)。

Also, could you point out a way whereby I can find out and print what the type is?另外,您能否指出一种我可以找出并打印类型的方法? for eg if its an rvalue of type int then I should be able to print out that int&& was passed?例如,如果它是int类型的rvalue ,那么我应该能够打印出int&&已通过? (I've been using std::is_same to check but manually.) (我一直在使用std::is_same来手动检查。)

Thank you for your time.感谢您的时间。

why is it that there are specializations for lvalue and rvalue reference?为什么有左值和右值引用的特化?

If only the primary template existed, then doing:如果仅存在主模板,则执行以下操作:

remove_reference<int&>::type

Would give you:会给你:

int&

And doing:并做:

remove_reference<int&&>::type

Would give you:会给你:

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.左值引用和右值引用的特化允许分别从您传递的类型参数中剥离&&&

For instance, if you are doing:例如,如果您正在执行以下操作:

remove_reference<int&&>

The type int&& will match the pattern specified by the T&& specialization, with T being int .类型int&&将匹配T&&指定的模式,其中Tint Since the specialization defines the type alias type to be T (in this case, int ), doing:由于特化将类型别名type定义为T (在本例中为int ),因此执行以下操作:

remove_reference<int&&>::type

Will give you int .会给你int

could you explain how, why we cast to remove_reference<t>::type&& in move ?你能解释如何,为什么我们投来remove_reference<t>::type&&move

That's because if move() were defined as follows:那是因为如果move()定义如下:

    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)

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").如果move()的参数是X类型的左值(这就是所谓的“通用引用”),则返回类型将为X& We want to make sure that the return type is always an rvalue reference.我们要确保返回类型始终是右值引用。

The purpose of move() is to give you back an rvalue, no matter what you pass in input. move()的目的是给你一个右值,无论你传入什么输入。 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.由于对返回类型为右值引用的函数的函数调用是右值,我们确实希望move()始终返回右值引用。

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.这就是我们执行remove_reference<T>::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!");
    // ...
}

Which relies on the fact that when an lvalue of type X is being passed, T will be deduced to be X& .这依赖于这样一个事实,即当传递X类型的左值时, T将被推导出为X&

You could also use an equivalent SFINAE-constraint, if you only want to produce a substitution failure:如果您只想产生替换失败,您也可以使用等效的 SFINAE 约束:

#include <type_traits>

template<typename T, typename std::enable_if<
    !std::is_reference<T>::value>::type* = nullptr>
void foo(T&&)
{
    // ...
}

When you treat some type as template parameter, compiler searches for the most "specialized" specialization.当您将某种类型视为模板参数时,编译器会搜索最“专业”的专业化。 If you pass a int&& to this template, compiler use remove_reference<T&&> version.如果将 int&& 传递给此模板,则编译器使用remove_reference<T&&>版本。 General specialization don't give you what you want - if you pass int&& to general specialiation, type will be int&&一般专业不给你你想要的 - 如果你将int&&传递给一般专业,类型将是int&&

If you want to print type, use typeid(some_type).name()如果要打印类型,请使用typeid(some_type).name()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM