2 votes

Erreur d'opérande illégal sur un itérateur de pointeur de fonction

Je reçois les erreurs suivantes :

  1. '<' : illégal, l'opérande de gauche est de type 'const_Ty'.
  2. '> : illégal, l'opérande de droite est de type 'const_Ty'.

dans le code ci-dessous.

Il s'agit d'un itérateur relativement simple sur une carte de pointeurs de fonctions où les fonctions sont de la forme void (Game::*)(UINT) . Je vérifie la valeur par rapport à un flottant, puis j'exécute la fonction. Le problème semble se situer au niveau du for bien que j'aie une autre boucle for sensiblement similaire quelque part ailleurs qui fonctionne sans problème.

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);
        }
    }
}

1voto

Turtlefight Points 3331

Pointeurs de fonctions membres ne pas implémenter operator< qui est la fonction de tri par défaut std::map utilise.

Les pointeurs de fonctions membres n'implémentent que operator== et operator!= .

Une façon simple de résoudre ce problème serait d'avoir une clé séparée et de mettre le pointeur de fonction dans la valeur de la carte, par exemple :

std::map<int, std::pair<FuncPtr, float>>

ou si vous n'avez pas besoin de la recherche rapide de std::map un simple vecteur ferait également l'affaire :

std::vector<std::pair<FuncPtr, float>>

Une autre approche consisterait à utiliser le type de pointeur de fonction comme clé :

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);
        }
    }
}

Cette méthode utilise essentiellement le pointeur de fonction spécifique comme clé unique.

Vous pourriez alors ajouter de nouvelles entrées comme ceci :

funcDelayedTriggerMap.emplace(typeid(Tag<&Game::DoIt>), DelayedTrigger{&Game::DoIt, 1.0f});
// or
funcDelayedTriggerMap[typeid(Tag<&Game::DoIt>)] = {&Game::DoIt, 1.0f};

Et vérifier si une fonction est présente :

if(funcDelayedTriggerMap.contains(typeid(Tag<&Game::DoIt>))) {
  // ...
}

Cela ne fonctionne toutefois que si vous connaissez toutes les fonctions que vous souhaitez utiliser avec la carte au moment de la compilation.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X