首页 > 解决方案 > std::function 对象的 C++ 映射抛出“未能专门化函数模板”错误

问题描述

我很难解决与我的 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);
}

从地图调用工厂的方法:

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;

,它也没有显示任何错误,但在编译时以相同的结果结束。我花了几个小时试图解决这个问题,但不知道可能是什么问题。非常感谢任何帮助/提示:)

标签: c++std-functionstdbind

解决方案


您忘记了第一个占位符:

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

您还可以使用 lambda:

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

演示


推荐阅读