你如何理解"std: :forward is just syntactic sugar"?这是真的吗?

How do you comprehend "std: :forward is just syntactic sugar"? Is that true?

本文关键字:syntactic sugar 是真的吗 just forward 何理解 std is      更新时间:2023-10-16

你如何理解"std::forward is just syntactic sugar"?这是真的吗? 如果您能详细解释下面的相关代码,我将不胜感激。

根据文档(https://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00416_source.html(, 以下是std::forward的实现:

/**
*  @brief  Forward an lvalue.
*  @return The parameter cast to the specified type.
*
*  This function is used to implement "perfect forwarding".
*/
template<typename _Tp>
constexpr _Tp&&
forward(typename std::remove_reference<_Tp>::type& __t) noexcept
{ return static_cast<_Tp&&>(__t); }

/**
*  @brief  Forward an rvalue.
*  @return The parameter cast to the specified type.
*
*  This function is used to implement "perfect forwarding".
*/
template<typename _Tp>
constexpr _Tp&&
forward(typename std::remove_reference<_Tp>::type&& __t) noexcept
{
static_assert(!std::is_lvalue_reference<_Tp>::value, "template argument"
" substituting _Tp is an lvalue reference type");
return static_cast<_Tp&&>(__t);
}
/**
*  @brief  Convert a value to an rvalue.
*  @param  __t  A thing of arbitrary type.
*  @return The parameter cast to an rvalue-reference to allow moving it.
*/
template<typename _Tp>
constexpr typename std::remove_reference<_Tp>::type&&
move(_Tp&& __t) noexcept
{ return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }

"std: :forward is just syntactic sugar"?这是真的吗?

取决于"只是句法糖"是什么意思。

你如何理解"std::forward is just syntactic sugar"?

我认为描述std::forward的正确且类似的方法是,它是一个非常简单的函数模板,可以在标准C++中实现。

换句话说,在标准库中提供std::forward对于程序员进行完美的转发不是必需的。

似乎真正的问题是:"std::forward做什么,为什么有必要?

std::forward可以称为static_cast的句法糖。通常(可能总是(它只做一个演员表。它将函数的参数转换为 r 值或 l 值引用,这在许多情况下是必需的,例如:

#include <iostream>
void f(int &) {
std::cout << "L-value referencen";
}
void f(int &&) {
std::cout << "R-value referencen";
}
template<typename T>
void g(T &&a) {
f(a);
}
template<typename T>
void h(T &&a) {
f(std::forward<T>(a));
}
template<typename T>
void i(T &&a) {
f(static_cast<T&&>(a));
}
int main() {
int a = 5;
g(a);
g(5);
h(a);
h(5);
i(a);
i(5);
}

指纹

L-value reference
L-value reference
L-value reference
R-value reference
L-value reference
R-value reference

函数调用g(5)调用f(int &)。这通常是意料之外的。

发生这种情况是因为所有函数参数都是 l 值。它们有一个名称,可以获取其地址并分配一个值,例如:

#include <iostream>
void f(int &) {
std::cout << " L-value referencen";
}
void f(int &&) {
std::cout << " R-value referencen";
}
void j(int &&a) {
std::cout << &a;
a = 6;
f(a);
}
void k(int &&a) {
std::cout << &a;
a = 6;
f(std::forward<int>(a));
}
int main() {
j(5);
k(5);
}

指纹

0x7ffc2db04ea8 L-value reference
0x7ffc2db04eac R-value reference

我理解这个问题的精神,但是,我不同意它的前提。

由于std::forward可以使用标准C++的语法来实现,因此它不是通常所说的"句法糖";也就是说,std::forward的实现不需要在语言中添加新的语法。"句法糖"是语言设计者添加的新语法,以提供一种不那么冗长的方式来表达所需的行为,但仍然可以使用该语言来表达。(如果它以前不是可表达的,那么它就不是句法糖;它是一个新的语言功能(

实际的句法糖确实是在C++11中添加的。基于范围的 for 循环是语法糖。

不管怎么说,至于问题的精神,要理解std::forward的实现需要了解两件事

  1. C++的引用折叠规则
  2. 只是"转发引用"与R值引用不同的一般想法 - Scott Meyers称之为"通用引用"。