I am getting the following errors:
- '<': illegal, left operand has type 'const_Ty'
- '>: illegal, right operand has type 'const_Ty'
in the below code.
It's a relative simple iterator on a function pointer map where the functions are of the form void (Game::*)(UINT)
. I check the value against a float, then run the function.
The problem seems to be in the for
line, although I've got another substantially similar for loop somewhere else that works without a problem.
using FuncPtr = void (Game::*)(UINT);
std::map<FuncPtr, float> funcDelayedTriggerMap;
void Game::PollProcessDelayedTriggers()
{
for (std::map<FuncPtr, float>::iterator it = funcDelayedTriggerMap.begin(); it != funcDelayedTriggerMap.end(); it)
{
float currentS = m_timer.GetElapsedSeconds();
if (it->second < currentS)
{
(this->*(it->first))(UINT_MAX);
funcDelayedTriggerMap.erase(it->first);
}
}
}
CodePudding user response:
Member function pointers don't implement operator<, which is the default sorting function std::map
uses.
Member function pointers only implement operator== and operator!= .
An easy way to fix this woud be to have a separate key and put the function pointer into the value of the map, e.g.:
std::map<int, std::pair<FuncPtr, float>>
or if you don't need the fast lookup of std::map
, a simple vector would also work:
std::vector<std::pair<FuncPtr, float>>
An alternative approach would be to use the function pointer type as key:
using FuncPtr = void (Game::*)(int);
// Just a helper to get a unique type for each function pointer
template<FuncPtr ptr>
struct Tag {};
struct DelayedTrigger {
FuncPtr ptr;
float value;
DelayedTrigger() : ptr(nullptr), value(0.0f) {}
DelayedTrigger(FuncPtr _ptr, float _value) : ptr(_ptr), value(_value) {}
};
std::map<std::type_index, DelayedTrigger> funcDelayedTriggerMap;
void Game::PollProcessDelayedTriggers()
{
for (std::map<std::type_index, DelayedTrigger>::iterator it = funcDelayedTriggerMap.begin(); it != funcDelayedTriggerMap.end(); it)
{
float currentS = 1.0;
if (it->second.value < currentS)
{
(this->*(it->second.ptr))(0);
funcDelayedTriggerMap.erase(it->first);
}
}
}
This essentially uses the specific function pointer as a unique key.
You could then add new entries like this:
funcDelayedTriggerMap.emplace(typeid(Tag<&Game::DoIt>), DelayedTrigger{&Game::DoIt, 1.0f});
// or
funcDelayedTriggerMap[typeid(Tag<&Game::DoIt>)] = {&Game::DoIt, 1.0f};
And check if a function is present:
if(funcDelayedTriggerMap.contains(typeid(Tag<&Game::DoIt>))) {
// ...
}
This however only works if you know all the functions you want to use with the map at compile time.