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

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

你如何理解"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”? Is that true?

取决于 "is just syntactic sugar" 的意思。

How do you comprehend “std: :forward is just syntactic sugar”?

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

也就是说,标准库中提供std::forward对于程序员做完美转发来说并不是必须的

看来真正的问题是:"What does std::forward do and why is it necessary?"

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

#include <iostream>

void f(int &) {
    std::cout << "L-value reference\n";
}

void f(int &&) {
    std::cout << "R-value reference\n";
}

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 &)。这通常不是预期的。

发生这种情况是因为所有函数参数都是左值。他们有一个名字,可以取它的地址并赋值,例如:

#include <iostream>

void f(int &) {
    std::cout << " L-value reference\n";
}

void f(int &&) {
    std::cout << " R-value reference\n";
}

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++的语法实现,所以不是通常所说的"syntactic sugar";也就是说,std::forward 的实现不需要在语言中添加新的语法。 "Syntactic sugar" 是一种语言的设计者添加的新语法,它提供了一种更简洁的方式来表达所需的行为,但仍然可以使用原来的语言来表达。 (如果它以前不能表达,那么它就不是语法糖;它是一种新的语言特性)

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

无论如何,至于问题的精神,要理解std::forward的实现你需要了解两件事

  1. C++ 的引用折叠规则
  2. 只是 "forwarding references" 与 R 值引用不同的一般想法——Scott Meyers 所说的 "universal references"。