Функция шаблона для выполнения обратного вызова члена на шаблонном объекте без предоставления его экземпляра - PullRequest
0 голосов
/ 17 мая 2018

Некоторый контекст ...

  • У меня есть карта, содержащая векторы объектов в качестве значений.
  • Каждый вектор содержит объекты специализированного типа.
  • Ключикарт являются значениями перечисления, представляющего каждый тип, EnumObjType
  • Я получаю события, содержащие EnumObjType и ObjID.

Я пытаюсьсоздать шаблонную функцию для обработки объектов любого типа, и моя задача состоит в том, чтобы к этим идентификаторам объектов обращались с помощью методов специализированного класса.Чтобы обойти это, я пытаюсь добавить параметр к моей функции шаблона, который будет функцией, вызываемой для получения идентификатора SpecializedObj.

Вызов функции шаблона выглядит следующим образом:

bool processEvent<SpecializedObj>(iEvent, iObjMap, &SpecializedObj::getSpecializedId);

Определение:

template<typename ObjType>
bool processEvent(MyEvent* iEvent,  ObjMap* iObjMap, std::function<unsigned int(void)> iObjIdCall)
{
  // Reach the corresponding ObjType vector
  ObjMap::iterator it =  iObjMap->find(iEvent->getObjType());
  std::vector<BaseObject*> wObjVector = it->second;

  // Iterate over the vector's range  
  for(BaseObject* wBaseObjPtr : wObjVector)
  {
    // Cast into SpecializedObj
    ObjType* wSpecializedObjPtr = dynamic_cast<ObjType*>(wBaseObjPtr);

    // Test dynamic_cast result
    if(!wSpecializedObjPtr) {return false;}

    std::function<unsigned int(void)> callback = std::bind(iObjIdCall,*wSpecializedObjPtr);

    // Check if the SpecializedObjPtr's ID matches the event's DeviceId
    if(callback() != iEvent->getDeviceId()) {return false;}

    // work on SpecializedObj
    // ...
    return true
  }

И ниже довольно загадочной ошибки для моих глаз:

11>C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\functional(514) : error C2664: 'std::_Func_class<_Ret>::_Set' : cannot convert parameter 1 from '_Myimpl *' to 'std::_Func_base<_Rx> *'
11>        with
11>        [
11>            _Ret=const unsigned int
11>        ]
11>        and
11>        [
11>            _Rx=const unsigned int
11>        ]
11>        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
11>        C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\functional(514) : see reference to function template instantiation 'void std::_Func_class<_Ret>::_Do_alloc<_Myimpl,_Fret(__thiscall SpecializedObj::* const &)(void) const,_Alloc>(_Fty,_Alloc)' being compiled
11>        with
11>        [
11>            _Ret=const unsigned int,
11>            _Fret=const unsigned int,
11>            _Alloc=std::allocator<std::_Func_class<const unsigned int>>,
11>            _Fty=const unsigned int (__thiscall SpecializedObj::* const &)(void) const
11>        ]
11>        C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\functional(514) : see reference to function template instantiation 'void std::_Func_class<_Ret>::_Do_alloc<_Myimpl,_Fret(__thiscall SpecializedObj::* const &)(void) const,_Alloc>(_Fty,_Alloc)' being compiled
11>        with
11>        [
11>            _Ret=const unsigned int,
11>            _Fret=const unsigned int,
11>            _Alloc=std::allocator<std::_Func_class<const unsigned int>>,
11>            _Fty=const unsigned int (__thiscall SpecializedObj::* const &)(void) const
11>        ]
11>        C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\functional(514) : see reference to function template instantiation 'void std::_Func_class<_Ret>::_Reset_alloc<_Fret,SpecializedObj,std::allocator<_Ty>>(_Fret (__thiscall SpecializedObj::* const )(void) const,_Alloc)' being compiled
11>        with
11>        [
11>            _Ret=const unsigned int,
11>            _Fret=const unsigned int,
11>            _Ty=std::_Func_class<const unsigned int>,
11>            _Alloc=std::allocator<std::_Func_class<const unsigned int>>
11>        ]
11>        C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\functional(514) : see reference to function template instantiation 'void std::_Func_class<_Ret>::_Reset_alloc<_Fret,SpecializedObj,std::allocator<_Ty>>(_Fret (__thiscall SpecializedObj::* const )(void) const,_Alloc)' being compiled
11>        with
11>        [
11>            _Ret=const unsigned int,
11>            _Fret=const unsigned int,
11>            _Ty=std::_Func_class<const unsigned int>,
11>            _Alloc=std::allocator<std::_Func_class<const unsigned int>>
11>        ]
11>        C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\functional(675) : see reference to function template instantiation 'void std::_Func_class<_Ret>::_Reset<const unsigned int,SpecializedObj>(_Fret (__thiscall SpecializedObj::* const )(void) const)' being compiled
11>        with
11>        [
11>            _Ret=const unsigned int,
11>            _Fret=const unsigned int
11>        ]
11>        C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\functional(675) : see reference to function template instantiation 'void std::_Func_class<_Ret>::_Reset<const unsigned int,SpecializedObj>(_Fret (__thiscall SpecializedObj::* const )(void) const)' being compiled
11>        with
11>        [
11>            _Ret=const unsigned int,
11>            _Fret=const unsigned int
11>        ]
11>        C:\MyProject\ObjUpdater.cpp(29) : see reference to function template instantiation 'std::function<_Fty>::function<const unsigned int(__thiscall SpecializedObj::* )(void) const>(_Fx &&)' being compiled
11>        with
11>        [
11>            _Fty=const unsigned int (void),
11>            _Fx=const unsigned int (__thiscall SpecializedObj::* )(void) const
11>        ]
11>        C:\MyProject\ObjUpdater.cpp(29) : see reference to function template instantiation 'std::function<_Fty>::function<const unsigned int(__thiscall SpecializedObj::* )(void) const>(_Fx &&)' being compiled
11>        with
11>        [
11>            _Fty=const unsigned int (void),
11>            _Fx=const unsigned int (__thiscall SpecializedObj::* )(void) const
11>        ]

Когда я ранее работал с обратными вызовами, я всегда знал сс каким экземпляром объекта он будет связан, поэтому я передал бы его в качестве параметров функции с std::bind(&Foo::func, fooObj), но, похоже, он здесь не работает.

РЕДАКТИРОВАТЬ: я использую набор инструментов Visual Studio 2012 v110

1 Ответ

0 голосов
/ 17 мая 2018

Когда я ранее работал с обратными вызовами, я всегда знал, с каким экземпляром объекта он будет связан, поэтому я передавал его в качестве параметров функции с std::bind(&Foo::func, fooObj), но, похоже, здесь он не работает.

Если processEvent() получить iObjIdCall как std::function<unsigned int(void)>, при попытке связать его и сохранить результат std::bind() в объекте того же типа

std::function<unsigned int(void)> callback
    = std::bind(iObjIdCall,*wSpecializedObjPtr);

вы путаете компилятор.

Попробуйте определить processEvent() как получение указателя на метод вместо std::function;что-то вроде

template <typename ObjType>
bool processEvent (MyEvent* iEvent,  ObjMap* iObjMap, ObjType::*iObjIdCall)

, если я правильно помню синтаксис.

...