views:

2753

answers:

9
int main()
{
    switch(std::string("raj")) //Compilation error - switch expression of type illegal 
    {
    case"sda":
    }

}
+3  A: 

In C++ you can only use a switch statement on int and char

MasterMax1313
enum turns into int??
yesraaj
A char turns into an int, too.
strager
Pointers can, too. That means you can sometimes compile something that would make sense in a different language, but it won't run right.
David Thornley
+4  A: 

In C++ and C switches only work on integer types. Use an if else ladder instead. C++ could obviously have implemented some sort of swich statement for strings - I guess nobody thought it worthwhile, and I agree with them.

anon
agreed,but do you know what made this not possible to use
yesraaj
History? Switching on real numbers, pointers and structs (C's only other data types) doesn't make sanse, so C limitted it to integers.
anon
Especially if you switch on classes that allow implicit conversions you'll have a really good time once.
sharptooth
+9  A: 

The problem is that for reasons of optimization the switch statement in C++ does not work on anything but primitive types, and you can only compare them with compile time constants.

Presumably the reason for the restriction is that the compiler is able to apply some form of optimization compiling the code down to one cmp instruction and a goto where the address is computed based on the value of the argument at runtime. Since branching and and loops don't play nicely with modern CPUs, this can be an important optimization.

To go around this, I am afraid you will have to resort to if statements.

tomjen
Not all primitive types work either. Only integral types.
Shmoopty
A: 

You can't use string in switch case.Only int & char are allowed. Instead you can try enum for representing the string and use it in the switch case block like

enum MyString(raj,taj,aaj);

Use it int the swich case statement.

anil
+5  A: 

You can only use switch on primitive such as int, char and enum. The easiest solution to do it like you want to, is to use an enum.

#include <map>
#include <string>
#include <iostream.h>

// Value-Defintions of the different String values
static enum StringValue { evNotDefined,
                          evStringValue1,
                          evStringValue2,
                          evStringValue3,
                          evEnd };

// Map to associate the strings with the enum values
static std::map<std::string, StringValue> s_mapStringValues;

// User input
static char szInput[_MAX_PATH];

// Intialization
static void Initialize();

int main(int argc, char* argv[])
{
  // Init the string map
  Initialize();

  // Loop until the user stops the program
  while(1)
  {
    // Get the user's input
    cout << "Please enter a string (end to terminate): ";
    cout.flush();
    cin.getline(szInput, _MAX_PATH);
    // Switch on the value
    switch(s_mapStringValues[szInput])
    {
      case evStringValue1:
        cout << "Detected the first valid string." << endl;
        break;
      case evStringValue2:
        cout << "Detected the second valid string." << endl;
        break;
      case evStringValue3:
        cout << "Detected the third valid string." << endl;
        break;
      case evEnd:
        cout << "Detected program end command. "
             << "Programm will be stopped." << endl;
        return(0);
      default:
        cout << "'" << szInput
             << "' is an invalid string. s_mapStringValues now contains "
             << s_mapStringValues.size()
             << " entries." << endl;
        break;
    }
  }

  return 0;
}

void Initialize()
{
  s_mapStringValues["First Value"] = evStringValue1;
  s_mapStringValues["Second Value"] = evStringValue2;
  s_mapStringValues["Third Value"] = evStringValue3;
  s_mapStringValues["end"] = evEnd;

  cout << "s_mapStringValues contains "
       << s_mapStringValues.size()
       << " entries." << endl;
}
MarmouCorp
Why is this downvoted? It's a fairly good solution. (It would be better if the globals were made const somehow, though. Perhaps an accessor which initializes once, hinding the actual "const" map.)
strager
Better still, using "std::map<std::string, some_function_pointer>" would eliminate the need for the switch. It would also keep the function that contained the switch from becoming excessively large.
Skizz
+12  A: 

The reason why has to do with the type system. C/C++ doesn't really support strings as a type. It does support the idea of a constant char array but it doesn't really fully understand the notion of a string.

In order to generate the code for a switch statement the compiler must understand what it means for two values to be equal. For items like ints and enums, this is a trivial bit comparison. But how should the compiler compare 2 string values? Case sensitive, insensitive, culture aware, etc ... Without a full awareness of a string this cannot be accurately answered.

Additionally, C/C++ switch statements are typically generated as branch tables. It's not nearly as easy to generate a branch table for a string style switch.

JaredPar
The branch table argument shouldn't apply - that's only one possible approach available to a compiler author. For a production compiler, one has to frequently use several approaches depending on the complexity of the switch.
plinth
@plinth, I put it there mostly for historical reasons. A lot of the "why does C/C++ do this" questions can easily be answered by the history of the compiler. At the time they wrote it, C was glorified assembly and hence switch really was a convenient branch table.
JaredPar
@plinth (cont) yes they could have updated it since then but C/C++ is annoyingly slow at changing the way they do things. For instance, it took till C99 to get a boolean type into C!
JaredPar
+3  A: 

I think the reason is that in C strings are not primitive types, as tomjen said, think in a string as a char array, so you can not do things like:

switch (char[]) { // ...
switch (int[]) { // ...
grilix
Without looking it up, a character array would likely degenerate to a char *, which converts directly to an integral type. So, it might well compile, but it certainly won't do what you want.
David Thornley
well.. maybe you can.. but sure you should not do it.. :P
grilix
+3  A: 

As mentioned previously, compilers like to build lookup tables that optimize switch statements to near O(1) timing whenever possible. Combine this with the fact that the C++ Language doesn't have a string type - std::string is part of the Standard Library which is not part of the Language per se.

I will offer an alternative that you might want to consider, I've used it in the past to good effect. Instead of switching over the string itself, switch over the result of a hash function that uses the string as input. Your code will be almost as clear as switching over the string if you are using a predetermined set of strings:

enum string_code {
    eFred,
    eBarney,
    eWilma,
    eBetty,
    ...
};

string_code hashit (std::string const& inString) {
    if (inString == "Fred") return eFred;
    if (inString == "Barney") return eBarney;
    ...
}

void foo() {
    switch (hashit(stringValue)) {
    case eFred:
        ...
    case eBarney:
        ...
    }
}

There are a bunch of obvious optimizations that pretty much follow what the C compiler would do with a switch statement... funny how that happens.

D.Shawley
A: 

In c++ strings are not first class citizens. The string operations are done through standard library. I think, that is the reason. Also, C++ uses branch table optimization to optimize the switch case statements. Have a look at the link.

http://en.wikipedia.org/wiki/Switch_statement

chappar