3 votes

Comment mapper une chaîne de caractères à une fonction avec Visual Studio 2008 ?

Cette question fait référence à la question suivante posée : Utiliser une map STL de pointeurs de fonction

En C++11, j'utilise une map pour stocker une paire afin d'exécuter plus efficacement du code au lieu d'utiliser des if...else if...else if comme mentionné dans le lien de référence.

Le code est encapsulé dans une fonction membre, où this fait référence à la classe, permettant l'accès aux variables membres.

utilisation de f = std::function;
const static std::map doSumthin {
  {"cas 1", [this]() {
    // exécuter le code dans le cas 1
  }},
  {"cas 2", [this]() {
    // exécuter le code dans le cas 2
  }},
  …
};

auto it = doSumthin.find(someString);

if (it != doSumthin.end())
{
    it->second();
}

Cependant, je dois faire fonctionner la base de code dans VS 2008. Je ne suis pas sûr de la manière la plus optimale de reproduire le code ci-dessus pour qu'il fonctionne dans VS 2008 sans revenir à l'approche moins efficace des if...else if.

Puis-je obtenir des conseils concernant ce problème ?

4voto

robthebloke Points 1301
#include 
#include 

typedef void (*func_ptr_type)();

void func_case_1() {}
void func_case_2() {}

static std::map doSumthin;

void initMap()
{
    doSumthin["case 1"] = func_case_1;
    doSumthin["case 2"] = func_case_2;
}

int main()
{
    initMap();

    std::map::iterator it = doSumthin.find("case 1");
    if (it != doSumthin.end())
    {
        it->second();
    }
    return 0;
}

2voto

Kerndog73 Points 848

Je n'ai pas testé ceci spécifiquement sur VS2008 mais je suis assez sûr que c'est du C++98 valide.

#include 
#include 

class Foo {
  void case_1() {}
  void case_2() {}

  typedef std::map CaseMap; 

  static CaseMap initCases() {
    CaseMap cases;
    cases["case_1"] = &Foo::case_1;
    cases["case_2"] = &Foo::case_2;
    return cases;
  }

  static const CaseMap cases;

public:
  void execute(const std::string &name) {
    CaseMap::const_iterator iter = cases.find(name);
    if (iter != cases.end()) {
      void(Foo::*func)() = iter->second;
      (this->*func)();
    }
  }
};

const Foo::CaseMap Foo::cases = Foo::initCases();

Une autre possibilité est d'utiliser des X-macros. Je crois que c'est aussi proche que possible de l'extrait en C++11 (mais je ne le recommanderais pas).

#define CASES(X)        \
  X(case_1, {           \
    /* faire le cas 1 */     \
  })                    \
  X(case_2, {           \
    /* faire le cas 2 */     \
  })

#define DEFINE_FUNCTION(NAME, CODE) void NAME() CODE
#define INIT_MAP(NAME, CODE) cases[#NAME] = &Bar::NAME;

class Bar {
  CASES(DEFINE_FUNCTION)

  typedef std::map CaseMap;

  static CaseMap initCases() {
    CaseMap cases;
    CASES(INIT_MAP)
    return cases;
  }

  static const CaseMap cases;

public:
  void execute(const std::string &name) {
    CaseMap::const_iterator iter = cases.find(name);
    if (iter != cases.end()) {
      void(Bar::*func)() = iter->second;
      (this->*func)();
    }
  }
};

const Bar::CaseMap Bar::cases = Bar::initCases();

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