每次我写一个接受模板化可调用的签名时,我总是想知道参数的最佳类型是什么。它应该是值类型还是常量引用类型?
例如,
template <class Func>
void execute_func(Func func) {
/* ... */
}
// vs.
template <class Func>
void execute_func(const Func& func) {
/* ... */
}
是否存在可调用项大于64位(也称为指向func的指针(的情况?也许std::function
的行为不同?
通常,我不喜欢通过const引用传递callable
对象,因为它没有那么灵活(例如,它不能用于可变的lambda(。我建议按价值传递。如果检查stl算法的实现(例如,对于std::for_each
(,那么所有可调用对象也会通过值传递。
这样,如果需要,用户仍然可以使用std::ref(func)
或std::cref(func)
来避免不必要的可调用对象复制(使用reference_wrapper
(。
是否存在可调用大于64位的情况
根据我在CAD/CAE应用程序方面的工作经验,很多。函数可以很容易地保存大于64位的数据。在Visual Studio中,只需要超过两个以上的int
、多个double
、多个指针即可。
没有最好的类型。如果你有不可压缩函子呢?第一个模板将无法工作,因为它将尝试使用已删除的副本构造函数。你必须移动它,但这样你就会失去(可能(对对象的所有权。这完全取决于预期用途。是的,std::function可以比size_t大得多。如果绑定成员函数,它已经是2个字(对象指针和函数指针(。如果你把一些论点结合起来,它可能会进一步增长。lambda也是如此,每个捕获的值都存储在lambda中,在这种情况下,lambda基本上是一个函子。如果可调用函数具有非常量运算符,则常量引用将不起作用。它们都不适合所有用途。有时最好的选择是提供几个不同的版本,这样你就可以处理所有的情况,SFINAE是你的朋友。