Home > Software engineering >  c std::map compare function leads to runtime "bad_function_call"
c std::map compare function leads to runtime "bad_function_call"

Time:06-19

I'm declaring my std::map and use it below:

    map<int, int, function<bool (int, int)>> m;
    m.insert(make_pair(12,3));
    m.insert(make_pair(3,4));
    for(auto & p : m){
        cout << p.first << "," << p.second << endl;
    }

g compiles, no error. Template parameter only requires a type, but no function body is required, passes compilation. I was wondering how this empty comparer would behave. On running it:

terminate called after throwing an instance of 'std::bad_function_call'
  what():  bad_function_call

I only see this error in calling pure virtual function. But my code is using stl template, no polymorphism is in place.

So is this a c design issue, that compilation doesn't check if a function only has declaration but no function body to run? Plus, how would c standard deal with this?

Appreciate your explanations.

CodePudding user response:

The problem is not related to the template argument, but that you did not provide an actual value for it when constructing the map.

Note that in the documentation for the map constructor, there is a const Compare& parameter. It is via this parameter that you must give a value for your comparator which in this case is a lambda.

explicit map( const Compare& comp,
              const Allocator& alloc = Allocator() );

For example:

#include <functional>
#include <iostream>
#include <map>

using namespace std;

int main()
{
    auto comp = [](int a, int b) { return a > b; };
    map<int, int, function<bool (int, int)>> m(comp);
    m.insert(make_pair(12,3));
    m.insert(make_pair(3,4));
    for(auto & p : m){
        cout << p.first << "," << p.second << endl;
    }
}

Outputs:

12,3
3,4

CodePudding user response:

map<int, int, function<bool (int, int)>> m;

You declared std::map to use your own comparator whose signature is bool(int, int), but did not supply a callable functor.

You should declare a real callable object and pass it to constructor so that your map can call it when needed.

auto order_by_asc = [](int n1, int n2)->bool {return (n1 < n2); };
std::map<int, int, std::function<bool(int, int)>> m(order_by_asc);
  • Related