C++ support for string in switch-case

Jul 11, 2014 at 12:25pm
Just wondering if there's any plans in later revisions of C++ to include strings as possible cases in switch statements, like in C# or D? I understand that an enum can be used as a work-around for that, but it's just annoying if I have something like:

1
2
3
4
5
6
7
8
9
switch (file.getFilename()) // returns std::string
{
    case "somefile.dat":
        //...
        break;
    case "map2.dat":
        //...
        break;
}
Using enum instead, I'd have to make getFilename() return an int instead of a string... is there a better workaround or should I just stick to if-else statements?
Last edited on Jul 11, 2014 at 12:27pm
Jul 11, 2014 at 12:40pm
Stick to if statements.

This has been discussed in numerous threads:
http://www.cplusplus.com/search.do?q=switch+string

Jul 11, 2014 at 12:47pm
Sorry, I know, the main point of this thread was wondering if it had plans to be included in a standard at some point. Well, nevermind then.
Last edited on Jul 11, 2014 at 12:47pm
Jul 11, 2014 at 12:57pm
Switch is simple and as such unlikely to change.

Enums are essentially named values. You would have to map filenames to enums.


Filename to number:
1
2
3
4
5
6
7
8
9
const std::vector Names { "somefile.dat", "map2.dat" };

const auto name { file.getFilename() };
const auto elem { std::find( Names.begin(), Names.end(), name ) };
if ( elem != Names.end() )
{
  const auto pos { std::distance( Names.begin(), elem ) };
  std::cout << pos << '\n';
}

However, then you have to keep the Names and what you do with the number in sync.

How about a std::map that maps string to a function pointer?
Jul 11, 2014 at 1:10pm
Yep, a mapping would have to do, thanks.
Jul 11, 2014 at 1:16pm
closed account (z05DSL3A)
If(when) your compiler supports constexpr, you could make a hashing function along these lines:

constexpr unsigned int stringToInt(const char* str){...}

and use it:

1
2
3
4
5
6
7
switch (stringToInt(aString))
{
  case stringToInt("Hello"):
    break;
  case stringToInt("GoodBye"):
    break;
}


----------------------------------------------------------------------------------
Seems to work...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>

constexpr unsigned int string2int(const char* str, int h = 0)
{
    // DJB Hash function
    // not my code but can't remember where I got it from
    return !str[h] ? 5381 : (string2int(str, h+1)*33) ^ str[h];
}

int main(int argc, char** argv) 
{
	std::string str = "Say Hello";
	
	switch ( string2int(str.c_str()))
	{
	    case string2int("Say Hello"):
	        std::cout <<"Hello!";
	        break;
	    case string2int("Say Goodbye"):
	        std::cout << "Goodbye!";
	        break;
	}
	return 0;
}


With a little more 'manual' work you can do:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>

unsigned int string2int(const char* str, int h = 0)
{
	// DJB Hash function
	// not my code but can't remember where I got it from
	return !str[h] ? 5381 : (string2int(str, h + 1) * 33) ^ str[h];
}

int main(int argc, char** argv)
{
	std::string str = "Say Goodbye";

	switch (string2int(str.c_str()))
	{
	case /* Say Hello */ 1768126732: 
		std::cout << "Hello!";
		break;
	case /* Say Goodbye */ 3534692467:
		std::cout << "Goodbye!";
		break;
	default: std::cout << string2int(str.c_str());
	}
	return 0;
}
Last edited on Jul 11, 2014 at 2:40pm
Topic archived. No new replies allowed.