<tfoot id='Gu2Gr'></tfoot>

    <small id='Gu2Gr'></small><noframes id='Gu2Gr'>

    • <bdo id='Gu2Gr'></bdo><ul id='Gu2Gr'></ul>

      1. <i id='Gu2Gr'><tr id='Gu2Gr'><dt id='Gu2Gr'><q id='Gu2Gr'><span id='Gu2Gr'><b id='Gu2Gr'><form id='Gu2Gr'><ins id='Gu2Gr'></ins><ul id='Gu2Gr'></ul><sub id='Gu2Gr'></sub></form><legend id='Gu2Gr'></legend><bdo id='Gu2Gr'><pre id='Gu2Gr'><center id='Gu2Gr'></center></pre></bdo></b><th id='Gu2Gr'></th></span></q></dt></tr></i><div id='Gu2Gr'><tfoot id='Gu2Gr'></tfoot><dl id='Gu2Gr'><fieldset id='Gu2Gr'></fieldset></dl></div>
      2. <legend id='Gu2Gr'><style id='Gu2Gr'><dir id='Gu2Gr'><q id='Gu2Gr'></q></dir></style></legend>

        为什么 std::forward 有两个重载?

        Why does std::forward have two overloads?(为什么 std::forward 有两个重载?)

      3. <tfoot id='imkfB'></tfoot>
          <tbody id='imkfB'></tbody>
        <i id='imkfB'><tr id='imkfB'><dt id='imkfB'><q id='imkfB'><span id='imkfB'><b id='imkfB'><form id='imkfB'><ins id='imkfB'></ins><ul id='imkfB'></ul><sub id='imkfB'></sub></form><legend id='imkfB'></legend><bdo id='imkfB'><pre id='imkfB'><center id='imkfB'></center></pre></bdo></b><th id='imkfB'></th></span></q></dt></tr></i><div id='imkfB'><tfoot id='imkfB'></tfoot><dl id='imkfB'><fieldset id='imkfB'></fieldset></dl></div>

          <small id='imkfB'></small><noframes id='imkfB'>

          <legend id='imkfB'><style id='imkfB'><dir id='imkfB'><q id='imkfB'></q></dir></style></legend>

            • <bdo id='imkfB'></bdo><ul id='imkfB'></ul>

                • 本文介绍了为什么 std::forward 有两个重载?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                  问题描述

                  给定以下参考折叠规则

                  • T&& --> T&
                  • T&&& --> T&
                  • T&&& --> T&
                  • T&&&& --> T&&
                  • T& & --> T&
                  • T&& & --> T&
                  • T& && --> T&
                  • T&& && --> T&&

                  第三条和第四条规则意味着T(ref qualifer)&&是恒等变换,即T&停留在T&code> 和 T&& 保持在 T&&.为什么 std::forward 有两个重载?以下定义不能用于所有目的吗?

                  The third and fourth rule imply that T(ref qualifer) && is the identity transformation, i.e. T& stays at T& and T&& stays at T&&. Why do we have two overloads for std::forward? Couldn't the following definition serve all purposes?

                  template <typename T, typename = std::enable_if_t<!std::is_const<T>::value>>
                  T&& forward(const typename std::remove_reference<T>::type& val) {
                      return static_cast<T&&>(const_cast<T&&>(val));
                  }
                  

                  此处 const std::remove_reference& 服务的唯一目的是不进行复制.并且 enable_if 有助于确保仅在非 const 值上调用该函数.我不完全确定是否需要 const_cast 因为它不是引用本身就是 const.

                  Here the only purpose the const std::remove_reference<T>& serves is to not make copies. And the enable_if helps ensure that the function is only called on non const values. I'm not entirely sure whether the const_cast is needed since it's not the reference itself that's const.

                  由于 forward 总是使用显式模板参数调用,因此我们需要考虑两种情况:

                  Since forward is always called with explicit template parameters there are two cases we need to consider:

                  1. forward(val) 这里forwardT的类型就是T& 因此返回类型将是到 T&
                  2. 的身份转换
                  3. forward 这里forwardT的类型就是T&& 因此返回类型将是到 T&&
                  4. 的身份转换
                  1. forward<Type&>(val) Here the type of T in forward will be T& and therefore the return type will be the identity transformation to T&
                  2. forward<Type&&>(val) Here the type of T in forward will be T&& and therefore the return type will be the identity transformation to T&&

                  那么为什么我们需要 http://en.cppreference 中描述的两个重载.com/w/cpp/utility/forward?

                  So then why do we need two overloads as described in http://en.cppreference.com/w/cpp/utility/forward?

                  注意:我不确定 std::forward 是否曾经与 const 类型一起使用,但我禁用了 forward 在那种情况下,因为我从来没有见过这样使用它.在这种情况下,移动语义也没有真正意义.

                  Note: I am not sure if std::forward is ever used with const types, but I disabled forward in that case, because I have never seen it used like that. Also move semantics don't really make sense in that case either.

                  推荐答案

                  Howard Hinnant 的 answer 是一个很好的起点> 和 paper 关于 std::forward().

                  A good place to start would be Howard Hinnant's answer and paper on std::forward().

                  您的实现正确处理所有正常用例(T& --> T&T const& --> T const&T&& --> T&&).它无法处理的是常见且容易产生的错误,这些错误在您的实现中很难调试,但无法使用 std::forward() 进行编译.

                  Your implementation handles all the normal use-cases correctly (T& --> T&, T const& --> T const&, and T&& --> T&&). What it fails to handle are common and easy-to-make errors, errors which would be very difficult to debug in your implementation but fail to compile with std::forward().

                  鉴于这些定义:

                  struct Object { };
                  
                  template <typename T, typename = std::enable_if_t<!std::is_const<T>::value>>
                  T&& my_forward(const typename std::remove_reference<T>::type& val) {
                      return static_cast<T&&>(const_cast<T&&>(val));
                  }
                  
                  template <class T>
                  void foo(T&& ) { }
                  

                  我可以将非 const 引用传递给 const 对象,包括左值类型:

                  I can pass non-const references to const objects, both of the lvalue variety:

                  const Object o{};
                  foo(my_forward<Object&>(o));    // ok?? calls foo<Object&>
                  foo(std::forward<Object&>(o));  // error
                  

                  和右值变量:

                  const Object o{};
                  foo(my_forward<Object>(o));    // ok?? calls foo<Object>
                  foo(std::forward<Object>(o));  // error
                  

                  我可以将左值引用传递给右值:

                  I can pass lvalue references to rvalues:

                  foo(my_forward<Object&>(Object{}));   // ok?? calls foo<Object&>
                  foo(std::forward<Object&>(Object{})); // error
                  

                  前两种情况可能会修改原本是 const 的对象(如果它们被构造为 const,则可能是 UB),最后一种情况是传递一个悬空左值引用.

                  The first two cases lead to potentially modifying objects that were intended to be const (which could be UB if they were constructed const), the last case is passing a dangling lvalue reference.

                  这篇关于为什么 std::forward 有两个重载?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                  本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

                  相关文档推荐

                  C++ stl unordered_map implementation, reference validity(C++ stl unordered_map 实现,参考有效性)
                  C++: Is it possible to use a reference as the value in a map?(C++:是否可以使用引用作为映射中的值?)
                  Where ampersand quot;amp;quot; can be put when passing argument by reference?(其中符号“amp;通过引用传递参数时可以放置吗?)
                  Why can a non-const reference parameter be bound to a temporary object?(为什么可以将非常量引用参数绑定到临时对象?)
                  What is a dangling reference?(什么是悬空引用?)
                  C++ reference changes when push_back new element to std::vector(当 push_back 新元素到 std::vector 时,C++ 引用发生变化)
                    <bdo id='VDf8o'></bdo><ul id='VDf8o'></ul>

                        <small id='VDf8o'></small><noframes id='VDf8o'>

                      • <legend id='VDf8o'><style id='VDf8o'><dir id='VDf8o'><q id='VDf8o'></q></dir></style></legend>

                          <tfoot id='VDf8o'></tfoot>
                        1. <i id='VDf8o'><tr id='VDf8o'><dt id='VDf8o'><q id='VDf8o'><span id='VDf8o'><b id='VDf8o'><form id='VDf8o'><ins id='VDf8o'></ins><ul id='VDf8o'></ul><sub id='VDf8o'></sub></form><legend id='VDf8o'></legend><bdo id='VDf8o'><pre id='VDf8o'><center id='VDf8o'></center></pre></bdo></b><th id='VDf8o'></th></span></q></dt></tr></i><div id='VDf8o'><tfoot id='VDf8o'></tfoot><dl id='VDf8o'><fieldset id='VDf8o'></fieldset></dl></div>
                            <tbody id='VDf8o'></tbody>