0

As I googled std::function works slower than simple lambda function.

Consider the following use case will there be std::function penalty when using stl sorting algorithms (v vector may be big enough and occupy about N*GB of data):

#include <iostream>
#include <functional>
#include <algorithm>
#include <vector>

using namespace std;

void sorter(std::vector<int>& v, std::function<bool(int a, int b)> f){
    std::sort(v.begin(), v.end(), f);
}

int main()
{
    std::vector<int> v = {5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
    for (auto val : v)
        cout << val << " ";
    cout << endl;

    int c = 4;
    auto f = [&c](int a, int b){ return a+b < c; };
    
    sorter(v, f);

    for (auto val : v)
        cout << val << " ";
    cout << endl;

    return 0;
}

As you can see I create the lambda function f and pass it to a sorter function. My task is to keep sorter function non-templated that is why I tried to pass lamda function as std::function. Or are there better ways of doing that?

Kerim
  • 171
  • 3
  • 10
  • 2
    Since the lambda function is **non-capturing**, you could have the parameter accept a *function pointer* instead. – Eljay Aug 06 '22 at 14:22
  • 2
    Non-captured lambdas can be converted to function pointers, so you can directly `void sorter(std::vector& v, bool(*f)(int, int))`. – 康桓瑋 Aug 06 '22 at 14:30
  • @Eljay I slightly modified the code to make lambda capturing. May we solve the same question now? – Kerim Aug 06 '22 at 14:50
  • 2
    No, with a capture your options are to use a template or a `std::function` (or another type erasure similar to `std::function`). – aschepler Aug 06 '22 at 14:59
  • 1
    You can create your own type erasure that is lighter weight than `std::function`. [Example](https://gcc.godbolt.org/z/r314rqj35). – Raymond Chen Aug 06 '22 at 15:16
  • 1
    As far as I understand the performance issue, a template might be faster because the compiler is probably inline the code into the algorithm. In practice unless you have to sort large amount of data with trivial comparison, the overhead should not matter much. – Phil1970 Aug 06 '22 at 15:41

1 Answers1

2

Lambdas that do not capture anything can be converted to a function pointer with the + operator:

void sorter(std::vector<int>& v, bool (*cmp)(int,int));

int main() {
  auto const cmp = +[](int a, int b) { return a < b; };
  vector<int> v{3, 2, 1};
  sorter(v, cmp);
}

But if it does capture something, you should either make it a template, or use std::function. No way around that.

Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93