如何使用 Visual Studio 2008 将字符串映射到函数?

How to map a string to a function with Visual Studio 2008?

此问题引用了以下问题: Using a STL map of function pointers

在 C++11 中,我使用映射来存储 <string, function> 对以更有效​​地执行代码,而不是使用 link 提到的 if...else if...else if

代码封装在成员函数中,其中this指的是class,允许访问成员变量。

using f = std::function<void()>;
static const std::map<std::string, f> doSumthin{
  {"case 1", [this]() {
    // execute code in case 1
  }},
  {"case 2", [this]() {
   // execute code in case 2
  }},
  …
};

auto it = doSumthin.find(someString);

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

但是,我需要使代码库在 VS 2008 中工作。我不确定在不恢复到效率较低的情况下复制上述代码以在 VS 2008 中工作的最佳方法是什么if...else if.

关于这个问题,我可以获得一些指导吗?

#include <map>
#include <string>

typedef void (*func_ptr_type)();

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

static std::map<std::string, func_ptr_type> doSumthin;

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

int main()
{
    initMap();

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

我没有在 VS2008 上专门测试过它,但我相当确定它是有效的 C++98。

#include <map>
#include <string>

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

  typedef std::map<std::string, void(Foo::*)()> 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();

另一种可能是使用X-macros。我相信这与 C++11 片段最接近(但我不建议使用它)。

#define CASES(X)        \
  X(case_1, {           \
    /* do case 1 */     \
  })                    \
  X(case_2, {           \
    /* do case 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<std::string, void(Bar::*)()> 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();