即使使用 C++11/14,"Why switch statement cannot be applied on strings?" 的答案仍然正确吗?

Is the answer given for "Why switch statement cannot be applied on strings?" still true, even with C++11/14?

我遇到了这个问题: Why switch statement cannot be applied on strings? 想知道答案是否:

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.

仍然适用,即使在 C++11/14 中使用 std:string。有几个 else if(...) 的替代方案吗?

是的,它仍然成立。
here所述,条件可以是:

any expression of integral or enumeration type, or of a class type contextually implicitly convertible to an integral or enumeration type, or a declaration of a single non-array variable of such type with a brace-or-equals initializer.

几天前我遇到了 that question,我想你可以从那里找到 if/else 链的替代解决方案。
如果可能的话,这主要取决于您的实际问题,无论如何,基本思想是使用可调用对象的映射,从中使用您的对象(在本例中为字符串)作为键进行访问。当然,在使用之前必须以某种方式填充该地图。

Is there an alternative to having severals else if(...)'s?

您可以编写自己的 switch 函数来代替 switch 语句。

也许看起来像这样:

#include <iostream>
#include <string>
#include <utility>
#include <tuple>

//pass in a bool as to whether or not we break
//make macro so it looks more like a switch statement
#define BREAK true

//template details used by outside functions
namespace switch_impl{

  //represents a case statement
  template <typename T, typename U>
  struct Case_Statement{
    U value;
    T expression;
    bool breaks;

    Case_Statement(U value, T expression, bool breaks=false)
    : value(value)
    , expression(expression)
    , breaks(breaks)
    {}

  };

  //recursive template unpacking to evaluate in a fashion similar to switch statements
  template<std::size_t I = 0, typename C, typename... Tp>
  inline typename std::enable_if<I == sizeof...(Tp), void>::type
    evaluate(C comparator, bool found, std::tuple<Tp...>& t)
    { }

  template<std::size_t I = 0, typename C, typename... Tp>
  inline typename std::enable_if<I < sizeof...(Tp), void>::type
    evaluate(C comparator, bool found, std::tuple<Tp...>& t)
    {
      if (std::get<I>(t).value == comparator || found){
        std::get<I>(t).expression();
        if (!std::get<I>(t).breaks){
          evaluate<I + 1, C, Tp...>(comparator,true,t);
        }
      }else{
          evaluate<I + 1, C, Tp...>(comparator,false,t);
      }
    }
}

//base functions to compose so that it looks like a switch statement
template<typename T, typename... Statements>  
void Switch(T comparator, Statements... statements)  
{
  auto t = std::make_tuple(statements...);
  switch_impl::evaluate(comparator,false,t);
}

template<typename T, typename U>
auto Case(U value, T expression, bool breaks=false) -> switch_impl::Case_Statement<T,U>{
  return switch_impl::Case_Statement<T,U>(value,expression,breaks);
}


//example usage
int main(){

  //c style switch example:
  switch (2){

    case 1:
    std::cout << "1\n";
    break;

    case 2:
    std::cout << "2\n";

    case 3: 
    std::cout << "3\n";
    break;

    case 4: 
    std::cout << "4\n";
    break;
  }

  //c++ functional switch example:
  Switch("2",

    Case("1",[&](){
      std::cout << "1\n";
    },BREAK),

    Case("2",[&](){
      std::cout << "2\n";
    }),

    Case("3",[&](){
      std::cout << "3\n";
    },BREAK),

    Case("4",[&](){
      std::cout << "4\n";
    },BREAK)
  );

}

我省略了默认大小写,但你明白了。
事实上,您可能会意识到这比常量表达式稍微强大一些。

欢迎来到模式匹配的世界,
这是一种语言功能,我认为 C++ could definitely use

替代方法是将字符串映射到 std::function,但如果您需要默认大小写,IMO 尤其是它非常难看。

#include <iostream>
#include <functional>
#include <string>
#include <map>

using namespace std;

static const map<string, function<void (const string&)>> handlers {
    { "AAPL", [](const auto& str) {cout << str << " Calif\n";}},
    { "MSFT", [](const auto& str) {cout << str << " Wash\n";}}
    };
static const function <void (const string&)> default_handler = [] (const auto& str) 
    {cout << str << " Narnia\n";};


void f(const string& str) {
    const auto it = handlers.find(str);
    if (it !=handlers.end()) {
        it->second(str);
    }
    else 
    {
        default_handler(str);
    }
}

int main() {
    f("ABC");
    f("AAPL");
    f("MSFT");;
}

c# 在内部执行此操作的方式是获取字符串的哈希码并对其进行切换。