所以这里的诀窍是std::less 和std::greater 实际上是可以简单构造的无状态函数对象。但它们不支持转换为函数指针。
有效的选择是(A)通过template 参数获取比较器并在标头中实现代码:
template<typename C> void myFunc( int a, int b, C comp )
这意味着您必须在头文件中实现它,或者 (B) 通过 std::function< bool(int, int) > 键入擦除函数对象:
void myFunc( int a, int b, std::function< bool(int, int) > comp )
这有一些成本(可能很重要?配置文件!)(通过针对无状态 std less/greater 的小对象优化来避免堆分配,但无论如何它往往会花费 virtual 函数调用,这也可能阻止内联)。
或者 (C) 编写一些代码,让您获取无状态函子并将其转换为函数指针:
template<typename T>
using Type = T;
template<typename StatelessFunctor>
struct function_ptr_of_stateless_t {
template<typename R, typename... Args>
operator Type<R(Args...)>*() const {
return [](Args... args)->R {
return StatelessFunctor()(std::forward<Args>(args)...);
};
}
};
template<typename StatelessFunctor>
function_ptr_of_stateless_t<StatelessFunctor> as_function_ptr() {
return {};
}
bool myFunction( int a, int b, bool(*comp)(int, int) ) { return comp(a,b); }
int main() {
std::cout << myFunction(3,7, as_function_ptr<std::less<int>>() ) << "\n";
}
template 函数 as_function_ptr 采用无状态函子的类型并创建一个丢弃类型,让您可以将其强制转换为任何兼容的函数指针类型。
这比std::function 解决方案的开销要小一些,因为对函数指针的调用往往比对virtual 方法的调用要快,此外,一些编译器(如gcc)在内联函数指针方面相当不错,甚至从一个编译单元到另一个编译单元。
作为奖励,在 C++14 中,您可以使用:
int main() {
std::cout << myFunction(3,7, as_function_ptr<std::less<>>() ) << "\n";
}
而且它仍然工作得非常好。