为什么模板化函子作为值传递而不转发参考 [英] Why is templated functor passed as value and not forwarding reference

查看:56
本文介绍了为什么模板化函子作为值传递而不转发参考的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在讨论中,我们在这里函子。 C ++ STL传递函子作为值(见 std :: for_each std :: find_if std :: transform

In discussion we had here I was playing around with passing functors. C++ STL passes functors as values (seen in std::for_each, std::find_if, std::transform)

所以声明我的就是这样。

So declaring mine would be like this.

template<typename F>
void call_me(F f)
{
    f();
}

现在,调用 call_me(ftor {})可能会调用 ftor 的副本构造函数(它很可能会被删除,而事实并非如此)。但是 ftor f {}; call_me(f); 将导致复制。如果 ftor 具有大数据,则可能是一个问题。

Now, calling call_me(ftor{}) could probably invoke ftor's copy constructor (it will most likely be copy elided, so not the case). But ftor f{}; call_me(f); will result in copying. If ftor has large data, it might be an issue.

我们将通过将其作为const进行传递来进行改进参考( void call_me(const F& f))摆脱不必要的副本。只要 ftor :: operator() const ,就可以了。如果不是,则对 call_me 的调用将导致编译错误(丢失 const 限定符)。

We'll improve it by passing it as const reference (void call_me(const F& f)) to get rid of unneeded copy. This is fine as long as ftor::operator() is const. If it is not, the call to call_me would result in compilation error (losing const qualifiers).

所以,为什么要打扰const引用,只使用引用( void call_me(F& f))。很好,但是对于第一种情况 call_me(ftor {})无效,因为将r值合并到(非const)l值引用无效

So, why to bother with const reference, use just reference (void call_me(F& f)). This is fine, but it would not work for first case being call_me(ftor{}) since binsing r-value to (non-const) l-value reference is not valid.

声明 f 作为转发参考( void call_me(F& f) )似乎在所有情况下都有效。我相信,这要归功于引用的折叠。

Declaring f as forwarding reference (void call_me(F&& f)) seems to work in all cases. I believe, that this works thanks to reference collapsing.

因此,为什么模板函子不能作为STL函数中的转发引用传递?

So, why are templated functors not passed as forwarding references in functions from STL?

推荐答案


为什么模板函子不能作为S值中的r值引用传递给STL函数?

why are templated functors not passed as r-value references in functions from STL?

首先,它们将是转发引用,而不是右值引用。

First of all, they'd be forwarding references, not rvalue references.

也就是说,与语言设计中的许多为什么问题一样,答案很简单:因为尚无人提出这一更改(请参见如何提交提案)。我怀疑传递到标准库算法中的大量函数对象要么是lambda,是无状态的,要么是可廉价复制的。而且,如果您有一个如此昂贵的对象,就算法而言,您总是可以将其变成可廉价复制的对象:

That said, as with many "why" questions about language design in general, the answer can simply be: because nobody has proposed this change yet (see how to submit a proposal). I suspect a great deal of function objects passed into the standard library algorithms are either lambdas, stateless, or extremely cheaply copyable. Moreover, if you have such an expensive object you can always turn in it into a cheaply copyable one for the purposes of the algorithm:

call_me(std::ref(huge_object));

最后,其中一些算法依赖于将这些函数对象传递给其他助手。如果算法仅假定函数对象是自由的复制对象,则可以轻松编写代码。如果我们在这里介绍右值的可能性,这会增加另一层需要处理的问题-我们是否只是传递参考?具有ref限定 operator()的函数对象怎么办?

Lastly, some of these algorithms rely upon passing these functions objects around to other helpers. If the algorithm simply assumes that the function object is "free" to copy, this makes it easy to code. If we introduce the possibility of rvalues here, this adds another layer of questions that need to be dealt with - do we just pass in the reference around? What about function objects with ref-qualified operator()?

上面的某些组合可能解释了为什么,例如,仍然如此:

Some combination of the above probably explains why, e.g., it's still:

template <class InputIt, class UnaryPredicate>
InputIt find_if(InputIt, InputIt, UnaryPredicate );

而不是

template <class InputIt, class UnaryPredicate>
InputIt find_if(InputIt, InputIt, UnaryPredicate&& );

这篇关于为什么模板化函子作为值传递而不转发参考的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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