const_forward在C++中的可选实现中做什么?

What does const_forward do in optional implementation in C++?

本文关键字:实现 什么 forward C++ const      更新时间:2023-10-16

嗨,我正在这里查看std::optional实现之一,我发现这个代码片段让我感到困惑:

// workaround: std utility functions aren't constexpr yet
template <class T> inline constexpr T&& constexpr_forward(typename 
std::remove_reference<T>::type& t) noexcept
{
return static_cast<T&&>(t);
}

所以我不以以下方式理解这一点:

  1. typename在这里做什么?只是声明以下部分是一个类型?
  2. 为什么我们需要std::remove_reference?我们不是在type&部分添加了引用吗?
  3. "std 效用函数还不是 constexpr"是什么意思?这个函数如何使它们变得通俗?它的身体只是一个static_cast.
  4. 这个函数在许多构造函数中使用,它看起来像这样:template <class... Args> constexpr storage_t( Args&&... args ) : value_(constexpr_forward<Args>(args)...) {},那么它在这里对 args 有什么作用?

多谢。

template <class T> inline constexpr T&& constexpr_forward(typename 
std::remove_reference<T>::type& t) noexcept
{
return static_cast<T&&>(t);
}
  1. typename在这里做什么?只是声明以下部分是一个类型?

std::remove_reference<T>::type是一个依赖于模板参数T依赖类型,因此我们需要typename告诉编译器我们正在尝试使用依赖名称

  1. 为什么我们需要std::remove_reference?我们不是在type&部分添加了引用吗?

如果您检查此实用程序函数的示例用法,如下所示

....
template <class... Args> explicit constexpr constexpr_optional_base(in_place_t, Args&&... args)
: init_(true), storage_(constexpr_forward<Args>(args)...) {}
...

您可以看到,可变参数 fowarding 引用类型用作显式模板参数来constexpr_foward<Args>(args)...。这将保留类型的值类别。当任何参数是引用时,就好像我们用constexpr_forward<Arg01&>(arg01)调用该实用程序函数一样。该模板的安装将是

inline constexpr Arg01&&& constexpr_forward(Arg01& t) noexcept
{
return static_cast<Arg01&&&>(t);
}

通过引用折叠规则,我们有

inline constexpr Arg01& constexpr_forward(Arg01& t) noexcept
{
return static_cast<Arg01&>(t);
}

实际上,删除引用应该是多余的(阅读有关引用折叠的信息(;

  1. "std 效用函数还不是 constexpr"是什么意思?这个函数如何使它们变得通俗?它的身体只是一个static_cast.

它只不过是在函数和构造函数constexpr中转发一个非constexpr函数。

  1. 这个函数在许多构造函数中使用,它看起来像这样:template <class... Args> constexpr storage_t( Args&&... args ) : value_(constexpr_forward<Args>(args)...) {},那么它在这里对参数有什么作用?

基本上如上所述..

您可能需要返回一步并做更多的阅读,此代码相当高级,您的问题表明您尚未阅读其中的一些内容。我会推荐斯科特·迈耶斯(Scott Meyers(的《现代有效C++》。至于您的具体问题:

  1. 是的,有必要使用typename,因为我们正在处理模板类的成员,这是一个依赖类型。把它想象成向编译器保证这个东西确实是一个类型,在编译器可以验证它之前的某个时刻(因为模板尚未实例化,只是定义,所以它不知道T是什么(。
  2. 与大多数模板函数不同,std::forward的想法是显式指定模板参数以使其正常工作。此形式禁用了在这种情况下可取的类型推导(罕见(。请注意,删除引用并重新添加它并不等同于什么都不执行,就好像它不是一开始的引用,它仍然以一个引用结束。这就是目标;始终采用左值引用。
  3. 这只是意味着它们没有被标记为constexpr.函数可以在常量表达式中使用,如果它被标记为constexpr。并非所有功能都可以标记为constexpr,存在限制。标准库函数std::forward可以是 constexpr,但事实并非如此。此函数只是一种解决方法。
  4. 这基本上等同于std::forward,所以最好用谷歌搜索一下并阅读它,因为这不是一件微不足道的事情(我提到的书谈到了它(。基本上这个想法是,一旦你有一个接受一组参数的函数,假设它想将这些参数转发到其他地方。问题是所有符号名称(在本例中为args(都被视为左值(即使它们是右值引用......正如我所说,这令人困惑,类型与值类别(。但是,如果用户传入了任何临时函数,那么我们希望将其正确转发(即作为临时函数(到下一个函数。std::forward确保作为右值传入的内容被强制转换为右值引用,并且可以由内部函数正确使用。

我希望这有所帮助。同样,您需要花一些时间阅读以更深入地了解价值类别,并重新引用以完全消化它。