Search code examples
c++hashcompiler-errorsstdmapstd-function

C++: How to make a container indexed by std::function?


For indexing I use std::unordered_map and std::map. Both of them throws compiling errors when using as follow:

std::unordered_map<std::function<bool(Ent*)>, int> var;

std::unordered_map fails due referencing deleted function

std::map fails due no < operator

The ideal solution for me would be to use a type of map, but if is a must to use another type of container, then it shouldn't be a problem


Solution

  • One way of having functions as container key is to wrap them into functor structure

    #include <unordered_map>
    #include <typeinfo>
    
    struct FunctorSum {
        int operator()(int x, int y) {
            return x + y;
        }
    };
    struct FunctorMult {
        int operator()(int x, int y) {
            return x * y;
        }
    };
    
    int main() {
        std::unordered_map<size_t, int> funcToInt;
        funcToInt[typeid(FunctorSum).hash_code()] = 0;
        funcToInt[typeid(FunctorMult).hash_code()] = 1;
    
        return 0;
    }
    

    Here I used typeid as hash, but it can also be hardcoded into functor struct.

    Another way is to use std::function::target_type to calculate hash of the function, which will work only with lambdas. But you can always wrap any function into lambda.

    #include <iostream>
    #include <functional>
    
    using FuncType = std::function<bool(int)>;
    bool x(int v) { return v == 0; }
    
    std::string hash(FuncType f) {
        return f.target_type().name();
    }
    
    int main() {
        auto y = [](int v) { return v == 1; };
        auto z = [](int v) { return v == 2; };
    
        std::cout << "x: " << hash(x) << std::endl;
        std::cout << "y: " << hash(y) << std::endl;
        std::cout << "z: " << hash(z) << std::endl;
    
        return 0;
    }
    

    Output

    x: PFbiE
    y: Z4mainEUliE_
    z: Z4mainEUliE0_