С ++ карта объектов std :: function выдает ошибку `` не удалось специализировать шаблон функции '' - PullRequest
0 голосов
/ 05 мая 2020

Мне сложно решить эту проблему, связанную с моим школьным проектом на C ++. По сути, мне нужна карта, в которой указан ключ GUID, а значение является функцией-членом MyClass, который является фабричным методом для экземпляров производных классов BaseClass, возвращаемых как указатель BaseClass. Код будет выглядеть так:

class MyClass{
private:
    std::map<GUID, std::function<BaseClass*(ClassX*, ClassY*, const GUID*)>> map;
    template<typename T>
    BaseClass* createInstance(ClassX* classX, ClassY* classY, const GUID* guid);
public:
    BaseClass* getDerivedInstance(ClassX* classX, ClassY* classY, const GUID* guid);
    //...
};

Заводской метод:

template<typename T>
BaseClass* MyClass::createInstance(ClassX* classX, ClassY* classY, const GUID* guid){
    return new T(classX, classY, guid);
}

Метод вызова factory из карты:

BaseClass* MyClass::getInstance(ClassX* classX, ClassY* classY, const GUID* guid){
    return map[*guid](classX, classY, guid);
}

В конструкторе я заполняю карта с фабричными методами (пока только с одним), например:

map[classGuid] = std::bind<BaseClass*>(&MyClass::createInstance<DerivedClassX>, this, std::placeholders::_3);

Класс MyClass является синглтоном, поэтому он заполняется только один раз. Код не показывает никаких ошибок, но при компиляции MSVS2019 выдает следующие ошибки:

'std :: invoke': не найдена соответствующая перегруженная функция Не удалось специализировать шаблон функции 'unknown-type std :: invoke (_Callable &&, _ Types && ...) noexcept ( ) '

Я даже пробовал сделать что-то вроде

using plain_fnc = BaseClass* (MyClass::*)(ClassX*, ClassY*, const GUID*);
using bind_eq = decltype(std::bind<BaseClass*>(std::declval<plain_fnc>(),
    std::declval<MyClass*>(), std::declval<const decltype(std::placeholders::_3)&>()));

bind_eq factory = std::bind<BaseClass*>(&MyClass::createInstance<DerivedClassX>, this, std::placeholders::_3);
map[classGuid] = factory;

, которое тоже не показывает никаких ошибок, но заканчивается тем же результатом при компиляции. Я потратил несколько часов, пытаясь решить эту проблему, но понятия не имею, в чем может быть проблема. Любая помощь / советы очень признательны :)

1 Ответ

1 голос
/ 05 мая 2020

Вы забыли первые заполнители:

map[classGuid] = std::bind<BaseClass*>(&MyClass::createInstance<DerivedClassX>, this,
    std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);

Вы также можете использовать лямбда:

map[classGuid] = [this](ClassX* classX, ClassY* classY, const GUID* guid) {
                     return createInstance<DerivedClassX>(classX, classY, guid);
                 };

Demo

...