Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么使用转发引用时需要std::forward?_C++_Templates_C++17_C++20 - Fatal编程技术网

C++ 为什么使用转发引用时需要std::forward?

C++ 为什么使用转发引用时需要std::forward?,c++,templates,c++17,c++20,C++,Templates,C++17,C++20,转发引用的定义如下: 转发引用是一种特殊的引用,它保留函数参数的值类别,从而可以通过std::forward转发函数参数 () 通过“保留函数参数的值类别”,我了解到类型为转发引用的参数变量的名称与函数调用中的值类别相同。 例如: template<typename T> void wrapper(T&& forwarded_argument) { some_function(forwarded_argument); } wrapper(5); wrappe

转发引用的定义如下: 转发引用是一种特殊的引用,它保留函数参数的值类别,从而可以通过std::forward转发函数参数 ()

通过“保留函数参数的值类别”,我了解到类型为转发引用的参数变量的名称与函数调用中的值类别相同。 例如:

template<typename T>
void wrapper(T&& forwarded_argument) {
    some_function(forwarded_argument);
}

wrapper(5);
wrapper(my_int);
正如cppreference()所述,对象类型的右值引用的强制转换表达式(如
static_cast(x)
)是一个xvalue。我没有看到任何关于
x
的值类别的提及,因此我假设整个cast表达式的值类别是相同的。函数调用表达式的值类别是xvalue,其返回类型是对对象的右值引用。由此看来,无论我将什么传递给
std::forward
,对
std::forward
的调用的值类别最终都将是一个xvalue

这里的错误在哪里?从通常的转发方式来看,问题两部分(关于转发引用和关于
std::forward
)的结论似乎都不正确

这里的错误在哪里

在这儿

这里,第一次调用中的表达式5是一个PR值,据我所知,
某个函数(forwarded\u argument)中的表达式
forwarded\u argument
(只是变量的名称),也应为prvalue

引用函数参数的id表达式(具体来说是普通标识符)是左值。我们需要强制转换它,以便将参数的值类别转换为函数。和
std::forward
根据推导模板参数中的编码值类别提供正确的强制转换

引用变量已绑定到参数(无论值类别如何)。因此,它现在作为一个名称,经验法则是,有名称的事物是左值1



1-只是经验法则。这在很大程度上是一种普遍的行为。这足以让人感觉到转发是如何工作的。

\u forwarded\u参数
始终是左值。请参阅:如果不是这样,那么定义中的“保留函数参数的值类别”部分到底意味着什么?它的意思是:
std::forward(arg)
与参数具有相同的值类别。但是
arg
本身并不存在。调用
wrapper
中的
不应该在那里,这是我的疏忽,我把它删掉了。
template <class T>
inline T&& forward(typename std::remove_reference<T>::type& t) noexcept {
    return static_cast<T&&>(t);
}

template <class T>
inline T&& forward(typename std::remove_reference<T>::type&& t) noexcept {
    static_assert(!std::is_lvalue_reference<T>::value, "Can not forward an rvalue as an lvalue.");
    return static_cast<T&&>(t);
}