您如何理解“ std :: forward只是语法糖”?是真的吗?

问题描述 投票:0回答:3

您如何理解“ std :: forward只是语法糖”?真的吗?如果您能在下面详细解释相关代码,我将不胜感激。

根据文档(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); }
c++ c++11 c++14 perfect-forwarding syntactic-sugar
3个回答
1
投票

“ std::forward只是语法糖”?是真的吗?

取决于一个词的“仅仅是语法糖”。

您如何理解“ std :: forward只是语法糖”?

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

换句话说,为了使程序员能够进行完美的转发,在标准库中不必提供std::forward


1
投票

似乎实际的问题是:“ std::forward是做什么的,为什么有必要?”

std::forward可以称为static_cast的语法糖。通常(可能总是),它只做强制转换。它将函数的参数强制转换为r值。左值参考,这在许多情况下是必需的,例如:]

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

之所以会这样,是因为所有函数参数都是l值。它们有一个名称,可以使用其地址并分配一个值,例如:

#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

1
投票

我理解问题的实质,但是我不同意其前提。

由于std :: forward可以使用标准C ++的语法实现,因此它不是通常所说的“语法糖”;也就是说,std :: forward不需要在语言中添加任何新颖的语法。 “语法糖”是一种语言的设计者所添加的新语法,它提供了一种更为冗长的方式来表达所需的行为,尽管如此,该行为仍可以使用该语言原样表达。

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

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

  1. C ++的参考折叠规则
  2. 只是“转发引用”与R值引用不同的一般概念-斯科特·迈耶(Scott Meyer)所说的“通用引用”。
© www.soinside.com 2019 - 2024. All rights reserved.