微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c – std :: forward没有完美的转发?

对std :: forward的建议通常限于完美转发函数模板参数的规范用例; some commentators到目前为止,这是唯一有效的使用std :: forward.但是考虑这样的代码
// Temporarily holds a value of type T,which may be a reference or ordinary
// copyable/movable value.
template <typename T>
class ValueHolder {
 public:
  ValueHolder(T value)
    : value_(std::forward<T>(value)) {
  }


  T Release() {
    T result = std::forward<T>(value_);
    delete this;
    return result;
  }

 private:
  ~ValueHolder() {}

  T value_;
};

在这种情况下,不会出现完美转发的问题:由于这是一个类模板而不是一个功能模板,因此客户端代码必须明确指定T,并可以选择是否以及如何参考资格.同样的道理,std :: forward的参数不是“通用引用”.

尽管如此,std :: forward似乎是一个很好的适合:我们不能只是离开它,因为它不会工作,当T是一个移动类型,我们不能使用std :: move,因为它会当T是一个左值引用类型时不工作.当然,我们可以将ValueHolder部分专门用于引用引用和std :: move作为值的直接初始化,但是当std :: forward执行此操作时,这似乎过于复杂.这也似乎是对std :: forward的意义的合理概念匹配:我们正在尝试一般地转发可能或可能不是引用的东西,只有我们将它转​​发给函数调用者,而不是我们称之为自己的功能

这是std :: forward的声音使用吗?有什么理由要避免吗?如果是这样,最好的选择是什么?

解决方法

std :: forward是一个有条件的转移(或更多的是技术上的rvalue转换),没有更多的.在完美的转发环境之外使用它是令人困惑的,如果移动中的相同条件适用,它可以做正确的事情.

我会尝试使用不同的名字,即使只是一个薄的包装在前面,但我不能想到一个好的上述情况.

或者使条件移动更明确.也就是说,

template<bool do_move,typename T>
struct helper {
  auto operator()(T&& t) const
  -> decltype(std::move(t))
  {
      return (std::move(t));
  }
};
template<typename T>
struct helper<false,T> {
  T& operator()(T&& t) const { return t; }
};
template<bool do_move,typename T>
auto conditional_move(T&& t)
 ->decltype( helper<do_move,T>()(std::forward<T>(t)) )
{
    return ( helper<do_move,T>()(std::forward<T>(t)) );
}

如果bool是false,那是一个noop pass-through,如果为true,则移动.然后,您可以使等同于-std :: forward更明确,更少依赖用户了解C11的神秘秘密来了解您的代码.

使用:

std::unique_ptr<int> foo;
std::unique_ptr<int> bar = conditional_move<true>(foo); // compiles
std::unique_ptr<int> baz = conditional_move<false>(foo); // does not compile

第三方面,你所做的这种事情需要对rvalue和lvalue语义的深刻理解,所以可能是前进是无害的.

原文地址:https://www.jb51.cc/c/114742.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐