繁体   English   中英

为什么编译器不选择 `forward` 的右值引用版本?

[英]Why compiler doesn't choose rvalue-reference version of the `forward`?

我写了一个类似的std::forward实现,希望找出在哪种情况下编译器会选择哪个版本。 问题是它似乎永远不会选择右值引用版本。

#include <type_traits>
#include <iostream>
#include <string>
#include <utility>

using std::string;
using std::cout;
using std::endl;
using std::remove_reference;
using std::move;

namespace explicit_return {
template <typename type> type&& forward(typename remove_reference<type>::type&  value) { cout << "cp-"; return static_cast<type&&>(value); }
template <typename type> type&& forward(typename remove_reference<type>::type&& value) { cout << "mv-"; return static_cast<type&&>(value); }
}

void print(string const & value) { cout << "c:" << value << endl; }
void print(string &  value)      { cout << "l:" << value << endl; }
void print(string && value)      { cout << "r:" << value << endl; }

template <typename type> void explicit_print(type && value) {          print(explicit_return::forward<type>(value)); }
template <typename type> void indirect_print(type && value) { explicit_print(explicit_return::forward<type>(value)); }

int main()
{
    string a("perfect");
    indirect_print(a);
    indirect_print(move(a));
    indirect_print("forward");
}

让我们看看output

cp-cp-l:perfect
cp-cp-r:perfect
cp-cp-r:forward

您传递给forward<type>的参数是一个变量,因此是一个l-value

当它是 r 值时,您可能会使用额外的std::move或额外的向前选择 r 值重载,例如:

template <typename type> void print_forward2(type&& value)
{
     print(explicit_return::forward<type>(explicit_return::forward<type>(value)));
}

演示

在实践中,我可以想象将 arguments 存储在tuple中并重新应用它们(一次),如下所示:

print(std::forward<Ts>(std::get<Ts>(std::move(my_tuple)))...);

尽管您已将indirect_print打印参数声明为type && ,但其值 class 不是右值,而是左值。 任何命名的 object 都是左值。

template <typename type>
void indirect_print(type && value) {
  explicit_print(explicit_return::forward<type>(value)); // `value` is lvalue here
}

这就是为什么你总是把你的forward称为type&版本。

删除explicit_printindirect_print并将main重写为:

int main()
{
    string a("perfect");

    print(explicit_return::forward<std::string>(a));
    print(explicit_return::forward<std::string>(move(a)));
    print(explicit_return::forward<std::string>("forward"));
}

你会看到不同之处:

cp-r:perfect
mv-r:perfect
mv-r:forward

暂无
暂无

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

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