switchで文字列を使いたい

C++ではできないので、マクロを使ってでっち上げる。

namespace ns_switch {
template<class C>
const C* select(const char* str, const wchar_t* wcs) { return str; }
template<>
const wchar_t* select<wchar_t>(const char* str, const wchar_t* wcs)
{ return wcs; }

template <class T, T v>
struct constant
{
  typedef T type;
  static const T value = v;
};
template <bool flag, class T, class U>
struct select_type
{
  typedef U type;
};
template <class T, class U>
struct select_type<true,T,U>
{
  typedef T type;
};
template <class T, class U>
struct is_same_type:ns_switch::constant<bool, false> {};
template <class T>
struct is_same_type<T,T>:ns_switch::constant<bool, true> {};
#define STR2(X) #X
#define STR(X) STR2(X)
#define WSTR(X) CAT(L,STR(X))
#define CAT2(X,Y) X##Y
#define CAT(X,Y) CAT2(X,Y)
#define SIZE(X) (sizeof(X)/sizeof((X)[0]))


template <class T>
struct switchtype
{
  typedef T type;
};
template <class T>
struct same_type
{ typedef T type; };

template <class CHAR>
struct switchtype<CHAR*>
{
  typedef std::basic_string<CHAR> type;
};
template <class CHAR,int N>
struct switchtype<const CHAR[N]>
{
  typedef std::basic_string<CHAR> type;
};
template <class CHAR,int N>
struct switchtype<CHAR[N]>
{
  typedef std::basic_string<CHAR> type;
};

template <class CHAR>
struct switchtype<const CHAR[]>
{
  typedef std::basic_string<CHAR> type;
};
template <class CHAR>
struct switchtype<CHAR[]>
{
  typedef std::basic_string<CHAR> type;
};
#define IS_SAME(X,Y) ns_switch::is_same_type<ns_switch::	\
	same_type<__typeof(X)>::type::value_type,Y>::value

#define SWITCHL CAT(_SWITCHL, __LINE__)
#define SWITCH(X) do { void* LABEL=0;				\
	const ns_switch::switchtype<__typeof(X)>::type&_(X); if(0)
#define CASE(Y)    COND(_== Y)
#define RANGE(X,Y) COND((X)<=_&&_<=(Y))
#define MATCH(X)						\
  COND(boost::regex_search(_,					\
    boost::basic_regex<ns_switch::same_type<__typeof(_)>	\
			::type::value_type>			\
      (ns_switch::select					\
      		<ns_switch::select_type<IS_SAME(_,char),	\
                		        char, wchar_t		\
                		       >::type			\
        	>(STR(X),WSTR(X))+1,				\
       ns_switch::select_type<IS_SAME(_,char),			\
                   ns_switch::constant<int, SIZE(STR(X))>,	\
                   ns_switch::constant<int, SIZE(WSTR(X))>	\
                   >::type::value-3,				\
       boost::regex_constants::match_default )))

#define COND(Y)  goto SWITCHL; } else if(Y) { SWITCHL:
#define DEFAULT  goto SWITCHL; } else { LABEL=&&SWITCHL; }	\
		if(0) { SWITCHL:
#define ENDSWITCH  else { if(LABEL) goto *LABEL; } } while(0)
} // end ns_switch

使い方のサンプル↓

int main(int argc, char **argv)
{
  for(int i = 1; i < argc; ++i){
    std::cout << argv[i] << "は";
    SWITCH(argv[i])
    {
      CASE("foo")
      CASE("bar")
        std::cout << "foo 又は barです" << std::endl;
        break;
      DEFAULT
        std::cout << "その他の文字列" << std::endl;
        break;
      RANGE("bc","de")
        std::cout << "bcとdeの間" << std::endl;
        break;
      CASE("hage")
        std::cout << "hageです ";
      MATCH("age")
        std::cout << "ageが含まれる文字列" << std::endl;
        break;
      MATCH("^\d+$")
        std::cout << "数字だけからなる文字列" << std::endl;
        break;
      COND(_[0]=='a')
        std::cout << "aで始まる文字列" << std::endl;
        break;
    }
    ENDSWITCH;
  }
  return 0;
}

GCC専用になってしまった。
正規表現を使うには、boostが必要。