Reputation: 33
I'm having hard time solving this issue related to my C++ school project. Basically, I need a map where the key is given GUID
and the value is a member function of MyClass
, which is a factory method for instances of derived classes of BaseClass
, returned as a BaseClass
pointer. The code would look like this:
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);
//...
};
Factory method:
template<typename T>
BaseClass* MyClass::createInstance(ClassX* classX, ClassY* classY, const GUID* guid){
return new T(classX, classY, guid);
}
Method to call factory from the map:
BaseClass* MyClass::getInstance(ClassX* classX, ClassY* classY, const GUID* guid){
return map[*guid](classX, classY, guid);
}
In constructor, i fill the map with factory methods (for now with just one) like this:
map[classGuid] = std::bind<BaseClass*>(&MyClass::createInstance<DerivedClassX>, this, std::placeholders::_3);
Class MyClass is a singleton, so it is filled just once.Code doesn't show any errors, but when compiled, MSVS2019 throws following errors:
'std::invoke': no matching overloaded function found Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...) noexcept()'
I even tried doing something like
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;
, which also doesn't show any errors, but ends with the same result when compiled. I spent a few hours trying to solve this, but have no clue what could be the issue.Any help/tips greatly appreciated :)
Upvotes: 0
Views: 134
Reputation: 118017
You forgot the first placeholders:
map[classGuid] = std::bind<BaseClass*>(&MyClass::createInstance<DerivedClassX>, this,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
You could also use a lambda:
map[classGuid] = [this](ClassX* classX, ClassY* classY, const GUID* guid) {
return createInstance<DerivedClassX>(classX, classY, guid);
};
Upvotes: 1