3

This question references the following asked question: Using a STL map of function pointers

In C++11, I am using a map to store a <string, function> pair to more efficiently execute code instead of using if...else if...else if as mentioned by the referenced link.

The code is encapsulated in a member function, where this refers to the class, allowing access to member variables.

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

However, I need to make the code base work in VS 2008. I'm not sure what the most optimal way to achieve replicate the above code to work in VS 2008 without reverting back to the less efficient if...else if.

Can I get some guidance in regards to this issue?

Indiana Kernick
  • 5,041
  • 2
  • 20
  • 50
Pangu
  • 3,721
  • 11
  • 53
  • 120
  • 1
    there's no C++2008 standard – phuclv Jan 09 '20 at 06:22
  • You could use function pointers instead of `std::function` – Indiana Kernick Jan 09 '20 at 06:22
  • Do you mean to say C++98(http://www.cplusplus.com/doc/oldtutorial/) ? – H S Jan 09 '20 at 06:22
  • Could you provide more context? What does `this` refer to? Is the map created inside a member function? Also, why is it `static`? Does the code that uses the map have access to the object that `this` refers to? – Indiana Kernick Jan 09 '20 at 06:29
  • @Kerndog73 updated the question...hopefully it's more clear – Pangu Jan 09 '20 at 06:32
  • VS2008 doesn't support C++11. (We switched to VS2013 to get least C++11 support at all.) So, I doubt that `std::function` is available. I doubt as well that `using` is supported the way you use it in `using f = std::function;`. Actually, I didn't try these modern things then we used VS2008 in the past. – Scheff's Cat Jan 09 '20 at 06:33

2 Answers2

4
#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;
}

robthebloke
  • 9,331
  • 9
  • 12
2

I haven't tested this on VS2008 specifically but I'm fairly sure it's valid 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();

Another possibility is to use X-macros. I believe this is as close as you can get to the C++11 snippet (but I wouldn't recommend using it).

#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();
Indiana Kernick
  • 5,041
  • 2
  • 20
  • 50