std :: forward没有完美的转发? [英] std::forward without perfect forwarding?

查看:89
本文介绍了std :: forward没有完美的转发?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于std::forward的建议通常限于完全转发函数模板参数的规范用例; 一些评论员甚至说这是 only 有效使用.但是考虑这样的代码:

Advice on std::forward is generally limited to the canonical use case of perfectly forwarding function template arguments; some commentators go so far as to say this is the only valid use of std::forward. But consider code like this:

// 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_);
    return result;
  }

 private:
  ~ValueHolder() {}

  T value_;
};

在这种情况下,不会出现完美转发的问题:由于这是类模板而不是功能模板,因此客户端代码必须显式指定T,并可以选择是否以及如何对其进行重新限定.同样,std::forward的参数也不是通用引用".

In this case, the issue of perfect forwarding does not arise: since this is a class template rather than a function template, client code must explicitly specify T, and can choose whether and how to ref-qualify it. By the same token, the argument to std::forward is not a "universal reference".

尽管如此,std::forward在这里似乎很合适:我们不能仅仅将其忽略掉,因为当T是仅移动类型时,它将不起作用,并且我们不能使用std::move因为当T是左值引用类型时,它将不起作用.当然,我们可以对ValueHolder进行部分专业化处理,以对引用使用直接初始化,对值使用std::move,但是当std::forward执行此操作时,这似乎过于复杂.这似乎与std::forward的含义在概念上是合理的匹配:我们试图通用地转发可能或可能不是引用的内容,只是将其转发给函数的调用者,而不是转发给我们自称为功能.

Nonetheless, std::forward appears to be a good fit here: we can't just leave it out because it wouldn't work when T is a move-only type, and we can't use std::move because it wouldn't work when T is an lvalue reference type. We could, of course, partially specialize ValueHolder to use direct initialization for references and std::move for values, but this seems like excessive complexity when std::forward does the job. This also seems like a reasonable conceptual match for the meaning of std::forward: we're trying to generically forward something that might or might not be a reference, only we're forwarding it to the caller of a function, rather than to a function we call ourselves.

这是std::forward的合理用法吗?有什么理由要避免吗?如果是这样,首选的替代方法是什么?

Is this a sound use of std::forward? Is there any reason to avoid it? If so, what's the preferred alternative?

推荐答案

std::forward是有条件的move强制转换(或更严格地说是右值强制转换),仅此而已.虽然在完美的转发上下文之外使用它会造成混淆,但是如果move上的相同条件适用,它就可以做正确的事情.

std::forward is a conditional move-cast (or more technically rvalue cast), nothing more, nothing less. While using it outside of a perfect forwarding context is confusing, it can do the right thing if the same condition on the move applies.

即使在forward上只有薄薄的包装纸,我也会尝试使用其他名称,但是我无法想到上述情况下的好包装纸.

I would be tempted to use a different name, even if only a thin wrapper on forward, but I cannot think of a good one for the above case.

或者使条件移动更明确.即,

Alternatively make the conditional move more explicit. Ie,

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,则为move.然后,您可以使等价于std::forward的内容更加明确,而更少地依赖于用户理解C ++ 11的奥秘秘诀来理解您的代码.

that is a noop pass-through if bool is false, and move if true. Then you can make your equivalent-to-std::forward more explicit and less reliant on the user understanding the arcane secrets of C++11 to understand your code.

使用:

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语义有相当深入的了解,因此forward可能是无害的.

On the third hand, the kind of thing you are doing above sort of requires reasonably deep understanding of rvalue and lvalue semantics, so maybe forward is harmless.

这篇关于std :: forward没有完美的转发?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆