简体   繁体   English

使用std :: greater或std :: less作为参数的参数

[英]Parameter to use std::greater or std::less as argument

I would like to make a function with a parameter that accepts either std::greater<int> or std::less<int> as the argument. 我想用一个接受std::greater<int>std::less<int>作为参数的参数创建一个函数。 I'm stuck on the syntax for the parameter, though. 不过,我仍然坚持参数的语法。

This is the format I tried: 这是我尝试的格式:

myFunction(int a, int b, bool *comp(int, int)) { … }
…
std::greater<int> bigger;
myFunction(2, 3, bigger);

That doesn't work, though, and I suspect the third parameter is just completely wrong. 但这不起作用,我怀疑第三个参数完全错误。 What should it actually be? 它到底应该是什么?

cannot convert std::greater<int> to bool* (*)(int, int) 无法将std::greater<int>转换为bool* (*)(int, int)

Functions taking a comparator are usually implemented via templates: 采用比较器的函数通常通过模板实现:

template <typename Comparator>
myFunction(int a, int b, Comparator comp) { … }

but you could also use std::function to implement it: 但你也可以使用std::function来实现它:

myFunction(int a, int b, std::function<bool (int, int)> ) { … }

The first version exposes code in the header but will usually perform better. 第一个版本公开了标题中的代码,但通常会表现得更好。 As for the second version, you can hide the implementation in the .cpp file, but you would lose some performance due to the impossibility to inline the comparator calls. 对于第二个版本,您可以隐藏.cpp文件中的实现,但由于无法内联比较器调用,您将失去一些性能。

So the trick here is that std::less and std::greater are actually stateless function objects that can be trivially constructed. 所以这里的技巧是std::lessstd::greater实际上是无状态函数对象,可以简单地构造。 But they don't support casting to a function pointer. 但是它们不支持转换为函数指针。

The efficient choices are either (A) take the comparator via template argument and implement the code in a header: 有效的选择是(A)通过template参数获取比较器并在头中实现代码:

template<typename C> void myFunc( int a, int b, C comp )

which means you have to implement it in a header file, or (B) type erase the function object via a std::function< bool(int, int) > : 这意味着你必须在头文件中实现它,或者(B)通过std::function< bool(int, int) >键入擦除函数对象:

void myFunc( int a, int b, std::function< bool(int, int) > comp )

which has some costs (maybe significant? Profile!) (heap allocation is avoided via small object optimization for stateless std less/greater, but it tends to cost a virtual function call regardless, which can also block inlining). 这有一些成本(可能很重要?Profile!)(通过对无状态std less / greater的小对象优化来避免堆分配,但无论如何都会花费virtual函数调用,这也会阻止内联)。

Or (C) write some code that lets you take a stateless functor and turn it into a function pointer: 或者(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";
}

where the template function as_function_ptr takes the type of your stateless functor and creates a throw away type that lets you cast it to any compatible function pointer type. 其中template函数as_function_ptr采用无状态as_function_ptr函数的类型,并创建一个抛弃类型,允许您将其转换为任何兼容的函数指针类型。

This has modestly less overhead than the std::function solution, as a call over a function pointer tends to be faster than over a virtual method, and in addition some compilers (like gcc) are quite decent at inlining function pointers, even from one compilation unit to another. 这比std::function解决方案的开销要小得多,因为对函数指针的调用往往比virtual方法更快,而且一些编译器(如gcc)在内联函数指针方面相当不错,即使从一个编译单元到另一个。

As a bonus, in C++14 you could use: 作为奖励,在C ++ 14中你可以使用:

int main() {
  std::cout << myFunction(3,7, as_function_ptr<std::less<>>() ) << "\n";
}

and it still works pretty optimally. 它仍然可以很好地工作。

Use a template: 使用模板:

template<class Callable>
myFunction(int a, int b, Callable f);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM