0
votes

I'm trying to pass a lambda as a sorting criterion to a set of indices of type int. I have used an unordered_map to map the indices to their values and passed it by value to the lambda which takes two indices and returns bool.

The code compiles but I'm getting "bad function call" error at run-time.

I've used std::function<> type wrapper to declare the lambda instead of using decltype() which was giving an error.

Code:

#include <iostream>
#include <unordered_map>
#include <functional>
#include <set>
#include <vector>

using namespace std;

int main()
{
    int T;
    cin >> T;

    while (T--)
    {
        int N;
        cin >> N;

        unordered_map<int, int> M;
        function<bool(int, int)> l = [M](int i1, int i2)->bool { return M.at(i1) > M.at(i2); };
        set<int, function<bool(int, int)>> S;
        for (int i = 1; i <= N; ++i)
        {
            int p;
            cin >> p;

            M[i] = p;
            S.insert(i);
        }

        vector<vector<int>> Adj(N + 1);
        for (int i = 1; i <= N - 1; ++i)
        {
            int u, v;
            cin >> u >> v;

            Adj[u].push_back(v);
            Adj[v].push_back(u);
        }

        int maximum = 0;
        for (int i = 1; i <= N; ++i)
        {
            S.erase(i);
            for (int e : Adj[i])
                S.erase(e);
            cout << *S.cbegin() << ' ';
            for (int e : Adj[i])
                S.insert(e);
            S.insert(i);
        }
        cout << endl;
    }
}

Input:

1
6
5 10 15 20 25 30
1 3
2 3
3 4
4 5
4 6

I have this code inside a try-catch block and it's printing "bad function call" when I enter the second value (10 in the input)

1
Please try to create a minimal reproducible example to show us. The code you show doesn't use the lambda. Or perhaps that is the problem? That you don't tell the set to use your lambda, and instead it attempts to use some unspecified function? - Some programmer dude
Are you trying to set a predicate for std::set by doing this: set<int, function<bool(int, int)>> S;? If so, I don't think the syntax is correct. - vahancho
You're capturing an empty map. Looking things up in it is a bad idea. - molbdnilo
Also watch out that [M] "captures by copy", meaning that changes to the M in the containing function won't have any effect on the M used inside the lambda. It looks like you want [&M] to "capture by reference". (But then make sure no copy of that std::function lives longer than M!) - aschepler
Before using std::function<>, I was using auto and passing the type in the set using decltype(l) and it was not compiling so I tried this and it compiled. Should I upload the whole code? - srt1104

1 Answers

1
votes

I have this code inside a try-catch block and it's printing "bad function call"

This happens when you try to invoke default initialized std::function:

std::bad_function_call if *this does not store a callable function target, i.e. !*this == true.

provided in documentation of std::function>::operator()

You do not pass your functor to std::set constructor when you initialize the object as you using default ctor for std::set:

set<int, function<bool(int, int)>> S; 

so this should be used instead:

set<int, function<bool(int, int)>> S( l ); 

and your lambda should capture M by reference as any changes you made later on M would not be reflected in this lambda as it captures M by value.