简体   繁体   English

需要在完美转发中衰减

[英]Need decay in perfect forwarding

I do not understand why the following code is not valid. 我不明白为什么以下代码无效。

#include <type_traits>
#include <tuple>

template<typename... Ts>
void funka( std::tuple<Ts...>&& v ) {    
}

template<typename T>
void funkb( T&& v ) {
    funka( std::forward<T>( v ) );
}

void funk() {
    auto tup = std::tuple<int,int>( 1, 2 );
    funkb( tup );
}

It fails with this error: 它失败并出现此错误:

<source>: In instantiation of 'void funkb(T&&) [with T = std::tuple<int, int>&]':
<source>:24:16:   required from here
<source>:10:10: error: cannot bind rvalue reference of type 'std::tuple<int, int>&&' to lvalue of type 'std::tuple<int, int>'
     funka( std::forward<T>( v ) );
     ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~

It compiles if I forward with a decay. 如果我带着腐烂forward ,它会编译。

template<typename T>
void funkb( T&& v ) {
    funka( std::forward<std::decay_t<T>>( v ) );
}

So the question is. 所以问题是。 Why is that not valid code? 为什么这不是有效的代码? To me it seems that the resulting parameter type of funkb and funka is the same. 对我而言,似乎funkbfunka的结果参数类型是相同的。

Thanks in advance 提前致谢

Why is that not valid code? 为什么这不是有效的代码?

In the funkb( tup ) call, tup is an lvalue . funkb( tup )呼叫, tup是一个左值 Due to forwarding reference deduction rules, the type of the argument v in funka is deduced as std::tuple<int, int>& . 由于转发参考演绎规则, funka参数v的类型推导为std::tuple<int, int>&

std::forward<std::tuple<int, int>&>( v ) doesn't move v - it still is an lvalue . std::forward<std::tuple<int, int>&>( v )不移动v - 它仍然是左值

Lvalue s do not bind to rvalue references . 左值不绑定到右值参考


It compiles if I forward with a decay. 如果我带着腐烂前进,它会编译。

std::decay_t removes all cv-qualifiers and references. std::decay_t删除所有cv限定符和引用。 It changes your forward call to something like: std::forward<std::tuple<int, int>>( v ) . 它将您的forward调用更改为: std::forward<std::tuple<int, int>>( v )

When std::forward is invoked with a non-reference or an rvalue reference as its template parameter, it will move v . 当使用非引用或右值引用作为其模板参数调用std::forward ,它将移动v

If you use decay and pass in an rvalue to funkb , then decay does nothing as the type is already "decayed" (ie it's T ). 如果你使用衰变并将rvalue传递给funkb ,那么衰变就没有任何作用,因为类型已经“腐朽”(即它是T )。

If you pass in an lvalue however, then the type of the forwarding reference is T& , and when you decay that, you get T . 但是,如果你传入左值,则转发参考的类型是T& ,当你衰减时,你得到T This means that the result of std::forward will be an rvalue in both cases. 这意味着std::forward的结果在两种情况下都是rvalue。

Now the code is not valid without decay because funka takes a rvalue reference, and you pass an lvalue to funkb which you then forward (preserving the value category). 现在代码在没有衰减的情况下无效,因为funka采用右值引用,然后将左值传递给funkb ,然后转发(保留值类别)。 You're basically doing 你基本上是在做

int a;
int&& b = a;

As you can see, with decay, you will always get an rvalue, which can bind to a rvalue reference. 正如您所看到的,通过衰减,您将始终获得一个rvalue,它可以绑定到右值引用。

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

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