Man*_*kka 8 c++ function-object
我有一个接收函数对象的模板化函数.有时函数对象是无状态结构,但有时它们是大型有状态对象.函数对象的状态在此函数中未更改,仅进行了检查.我也非常热衷于编写编译器可以尽可能优化的代码.选择参数类型时我应该考虑什么?
该功能属于以下类型:
template<typename funcT>
auto make_particle(funcT fun) {
Particle<typename funcT::result_type> particle;
particle = fun();
return particle;
}
Run Code Online (Sandbox Code Playgroud)
参数类型可能应该是funcT const & fun大型对象不被复制,但为什么大多数人使用按值调用的函数对象?我是否通过使用const引用来松散?或者我应该使用左值参考?请注意,c ++ 1y没问题,上面的代码示例只是一个例子.
有几个用例,应该都可用:
仿函数没有状态,并作为临时提供: make_particle(MyFun())
仿函数有一个需要稍后恢复的状态: YourFun f; make_particle(f);
你不能用一个引用类型参数来解决这两种情况:第一种情况需要一个const左值引用或一个rvalue引用,它禁止第二次使用,第二种情况需要一个左值引用,它禁止第一次使用.
在这种情况下常见的习语是按值接受仿函数,并在结尾处返回:
template <typename Iter, typename F>
F map(Iter first, Iter last, F f)
{
// ... f(*first) ...
return f;
}
Run Code Online (Sandbox Code Playgroud)
但是,这可能并不完全适用于您的情况,但这是一个想法.例如,你可以返回一个std::pair<ParticleType, F>.在任何情况下,您都需要您的仿函数类型可复制,但这是一个合理的要求.
另一个由@Xeo指出并且仅适用于函数模板的替代方法是通过通用引用来获取functor参数,这将适用于以下两种情况:
template <typename Iter, typename F>
void map(Iter first, Iter last, F && f)
{
// ... use f(*first) ...
}
Run Code Online (Sandbox Code Playgroud)
请注意,在这种情况下,我们不使用std::forward,因为我们使用它f作为真正的参考,而不仅仅是通过其他地方传递它.特别是,f如果我们仍然计划使用它,我们不允许迁移.
参数类型应该是funcT const&fun,这样就不会复制大对象,
这不是标准库中的算法所采用的视图.在那里,可调用对象按值获取.由可调用对象的作者来确保复制起来相当便宜.例如,如果它需要访问大的东西,那么你可以让仿函数的用户提供对一个的引用并将其存储在仿函数中 - 复制引用很便宜.
现在,您可能希望以与标准库不同的方式执行操作,因为您希望粒子制作功能异常难以复制或移动.但是C++程序员熟悉被复制的仿函数,所以如果你做了标准库所做的事情,那么你通常不会让他们的生活比现在更糟糕.复制仿函数不是问题,除非你把它变成一个:-)