形参使用std::greater或std::less作为实参

Parameter to use std::greater or std::less as argument

本文关键字:std 实参 less greater 形参      更新时间:2023-10-16

我想创建一个函数,其参数接受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::lessstd::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接受无状态函子的类型,并创建一个throw away类型,允许您将其强制转换为任何兼容的函数指针类型。

这比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);