views:

617

answers:

4

In other .NET languages such as C# you can switch on a string value:

string val = GetVal();
switch(val)
{
case "val1":
  DoSomething();
  break;
case "val2":
default:
  DoSomethingElse();
  break;
}

This doesn't seem to be the case in C++/CLI

System::String ^val = GetVal();
switch(val)  // Compile error
{
   // Snip
}

Is there a special keyword or another way to make this work for C++/CLI as it does in C#?

A: 

You certainly can't use anything other than an integer in a switch statement in C / C++. The easiest way to do this in C++ is to use and if ... else statement:

std::string val = getString();
if (val.equals("val1") == 0)
{
  DoSomething();
}
else if (val.equals("val2") == 0)
{
  DoSomethingElse();
}

Edit:

I just spotted you asked about C++/CLI - I don't know if the above still applies; it certainly does in ANSI C++.

Dave Rigby
switching on strings in c# is partly just syntactical sugar. when switching on an int the compiler uses a jump table with the value of the int used as the key, when switching on a string the resulting binary ressembles if-if-else-else (tho not by no means identical)
Rune FS
Actually, when switching on a string the C# compiler also makes a jump table. See http://stackoverflow.com/questions/395618/if-else-vs-switch
heavyd
+1  A: 

Actually, you can use anything other than integers (sometimes designated by integral types) if the tested objects defines conversion to integer.

String object do not.

However, you could create a map with string keys (check that the comparison is well processed) and pointers to classes implementing some interface as values:

class MyInterface {
  public:
    virtual void doit() = 0;
}

class FirstBehavior : public MyInterface {
  public:
    virtual void doit() {
      // do something
    }
}

class SecondBehavior : public MyInterface {
  public:
    virtual void doit() {
      // do something else
    }
}

...
map<string,MyInterface*> stringSwitch;
stringSwitch["val1"] = new FirstBehavior();
stringSwitch["val2"] = new SecondBehavior();
...

// you will have to check that your string is a valid one first...
stringSwitch[val]->doit();

A bit long to implement, but well designed.

dilig0
A: 

I think I found a solution on codeguru.com.

To1ne
A: 

I know my answer comes a little bit too late, but I think this is a good solution as well.

struct ltstr {
    bool operator()(const char* s1, const char* s2) const {
     return strcmp(s1, s2) < 0;
    }
};

std::map<const char*, int, ltstr> msgMap;

enum MSG_NAMES{
 MSG_ONE,
 MSG_TWO,
 MSG_THREE,
 MSG_FOUR
};

void init(){
msgMap["MSG_ONE"] = MSG_ONE;
msgMap["MSG_TWO"] = MSG_TWO;
}

void processMsg(const char* msg){
 std::map<const char*, int, ltstr>::iterator it = msgMap.find(msg);
 if (it == msgMap.end())
  return; //Or whatever... using find avoids that this message is allocated in the map even if not present...

 switch((*it).second){
  case MSG_ONE:
   ...
  break:

  case MSG_TWO:
  ...
  break;

 }
}
gotch4