![](/img/trans.png)
[英]If std::greater<>, then why std::less (and not std::lesser<>)?
[英]Parameter to use std::greater or std::less as argument
我想用一个接受std::greater<int>
或std::less<int>
作为参数的参数创建一个函数。 不过,我仍然坚持参数的语法。
这是我尝试的格式:
myFunction(int a, int b, bool *comp(int, int)) { … }
…
std::greater<int> bigger;
myFunction(2, 3, bigger);
但这不起作用,我怀疑第三个参数完全错误。 它到底应该是什么?
无法将
std::greater<int>
转换为bool* (*)(int, int)
采用比较器的函数通常通过模板实现:
template <typename Comparator>
myFunction(int a, int b, Comparator comp) { … }
但你也可以使用std::function
来实现它:
myFunction(int a, int b, std::function<bool (int, int)> ) { … }
第一个版本公开了标题中的代码,但通常会表现得更好。 对于第二个版本,您可以隐藏.cpp文件中的实现,但由于无法内联比较器调用,您将失去一些性能。
所以这里的技巧是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 )
这有一些成本(可能很重要?Profile!)(通过对无状态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
采用无状态as_function_ptr
函数的类型,并创建一个抛弃类型,允许您将其转换为任何兼容的函数指针类型。
这比std::function
解决方案的开销要小得多,因为对函数指针的调用往往比virtual
方法更快,而且一些编译器(如gcc)在内联函数指针方面相当不错,即使从一个编译单元到另一个。
作为奖励,在C ++ 14中你可以使用:
int main() {
std::cout << myFunction(3,7, as_function_ptr<std::less<>>() ) << "\n";
}
它仍然可以很好地工作。
使用模板:
template<class Callable>
myFunction(int a, int b, Callable f);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.