我一直在研究一些Boost源代码并注意到它们通过使用仿函数而不是普通函数来实现模板化函数?有这个原因吗?
例如:
template<typename Foo, typename Bar>
struct functor {
Bar operator()(const Foo& foo) {
return foo.as_bar();
}
};
而不是:
template<typename Foo, typename Bar>
Bar func(const Foo& foo) {
return foo.as_bar();
}
我能想到的唯一优势是它允许类继承函数吗?
答案 0 :(得分:2)
主要有两个原因:第一个原因是,正如pythonic比喻所指出的那样,部分特化只对类而不是函数有效。请注意,函数通常可以使用重载来克服此问题,但通常如果您正在进行元编程,则使用部分特化会更简单,更通用。我其实认为这是主要原因。
第二个原因是,只要代码想要接受一个函数对象(比如在STL中,例如std :: transform),它就会有一个类型模板参数。如果传递函子或lambda,则在编译时就知道确切的类型,并且不支付间接费用,并且可以执行内联。如果传递函数指针(或std :: function),则只在编译时知道签名,并且您需要支付间接费用(并且不能内联)。例如,使用仿函数而不是函数指针,std :: sort可以快得多。
请注意,有一个名为函数指针模板参数的小功能;这些是专门用于特定功能的非类型模板参数,因此可以删除间接。但是,如果您使用其中一个,则根本不能使用仿函数。因此,大多数想要接受函数对象的代码都是按照我上面描述的方式进行的。