C ++: Как создать контейнер, проиндексированный std :: function? - PullRequest
1 голос
/ 09 марта 2020

Для индексации я использую std::unordered_map и std::map. Оба из них выдают ошибки компиляции при использовании следующим образом:

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

std::unordered_map завершается неудачно из-за ссылки на удаленную функцию

std::map завершается неудачей из-за отсутствия оператора <

Идеальным решением для меня было бы использование типа map, но если необходимо использовать другой тип контейнера, то это не должно быть проблемой

1 Ответ

1 голос
/ 10 марта 2020

Один из способов иметь функции в качестве ключа контейнера - это обернуть их в структуру функтора

#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;
}

Здесь я использовал typeid как ha sh, но он также может быть жестко закодирован в структуру функтора.

Другой способ - использовать std :: function :: target_type для вычисления га sh функции, которая будет работать только с лямбдами. Но вы всегда можете заключить любую функцию в лямбду.

#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;
}

Вывод

x: PFbiE
y: Z4mainEUliE_
z: Z4mainEUliE0_
...