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

时间:2017-07-16 21:33:59

标签: c++ c++11 c++14 c++17

您好我正在here查看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); } 个实现之一,我发现此代码段让我感到困惑:

typename

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

  1. std::remove_reference在这做什么?只是声明以下部分是一种类型?
  2. 为什么我们需要type&?我们没有在static_cast部分添加引用吗?
  3. &#34; std实用程序功能还没有constexpr&#34;意思?这个函数如何使它们成为constexpr?它的主体只是template <class... Args> constexpr storage_t( Args&&... args ) : value_(constexpr_forward<Args>(args)...) {}
  4. 此函数在许多构造函数中使用,它看起来像这样:{{1}},那么它对args做了什么?
  5. 非常感谢。

2 个答案:

答案 0 :(得分:5)

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<T>::type依赖类型,它取决于模板参数T,因此我们需要typename告诉编译器我们正在尝试使用{ {3}},

  
      
  1. 为什么我们需要std::remove_reference?我们没有在type&部分添加引用吗?
  2.   

如果您在dependent-name

中查看此实用程序功能的示例用法
....
template <class... Args> explicit constexpr constexpr_optional_base(in_place_t, Args&&... args)
      : init_(true), storage_(constexpr_forward<Args>(args)...) {}
...

你可以看到,一个可变参与类型参考类型被用作constexpr_foward<Args>(args)...的显式模板参数。这将保留该类型的here。当任何参数是引用时,就好像我们用constexpr_forward<Arg01&>(arg01)调用该实用函数一样。并且该模板的实例将是

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

value category,我们有

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

实际上,删除引用应该在那里是多余的(阅读有关引用崩溃的内容);

  
      
  1. &#34; std实用程序功能还没有constexpr&#34;意思?这个函数如何使它们成为constexpr?它的主体只是static_cast
  2.   

constexpr函数和构造函数中只有reference collapsing ruleconstexpr函数。

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

基本上如上所述..

答案 1 :(得分:2)

您可能需要返回一步并进行更多阅读,此代码相当先进,您的问题表明您还没有阅读过这些内容。我推荐Scott Meyers的Modern Effective C ++。至于你的具体问题:

  1. 是的,有必要使用typename,因为我们正在处理模板类的成员,这是一个依赖类型。可以把它想象为确保编译器这个东西真的是一个类型,在编译器可以验证它之前(因为模板尚未实例化,只是定义了,所以它不知道T是什么)。
  2. 与大多数模板函数不同,std::forward的想法是明确指定模板参数以使其正常工作。此表单禁用类型推导,这在此上下文中是可取的(罕见)。请注意,删除引用并将其添加回来与不执行任何操作不同,就好像它不是引用的引用一样,它仍然最终为一个引用。那就是目标;总是采用左值参考。
  3. 这只是意味着它们未标记为constexpr。如果函数标记为constexpr,则可以在常量表达式中使用该函数。并非所有功能都可以标记为constexpr,但存在限制。标准库函数std::forward可以是constexpr,但根本不是。此功能只是解决方法。
  4. 这基本上相当于std::forward,所以最好去谷歌并阅读它,因为这不是一件容易的事情(我提到的那本书谈论它)。基本上这个想法是,一旦你有一个接受一组参数的函数,假设它想把这些参数转发到其他地方。问题是所有的符号名称(在这种情况下,args)都被认为是左值(即使它们是右值引用......正如我所说,它令人困惑,类型与值类别)。但是,如果用户传入任何临时值,那么我们希望它能够正确地(即作为临时)转发到下一个函数。 std::forward确保以rvalues方式传入的内容,被转换回rvalue引用,并可由内部函数正确使用。
  5. 我希望有所帮助。同样,您需要花一些时间阅读以更深入地了解值类别,并使用右值引用来完全消化它。