Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 是否给出了“的答案?”;为什么不能对字符串应用switch语句;即使使用C++;11/14?_C++_String_C++11_Std_Stdstring - Fatal编程技术网

C++ 是否给出了“的答案?”;为什么不能对字符串应用switch语句;即使使用C++;11/14?

C++ 是否给出了“的答案?”;为什么不能对字符串应用switch语句;即使使用C++;11/14?,c++,string,c++11,std,stdstring,C++,String,C++11,Std,Stdstring,我遇到了一个问题: 不知道答案是否是: 原因与类型系统有关。C/C++实际上不支持字符串作为类型。它确实支持常量字符数组的概念,但它并没有真正完全理解字符串的概念 即使使用C++11/14中的std:string,仍然适用。有没有一种方法可以代替几个,如果(…),它仍然有效。 如上所述,条件可以是: 整数或枚举类型的任何表达式,或上下文可隐式转换为整数或枚举类型的类类型的任何表达式,或使用大括号或equals初始值设定项声明此类类型的单个非数组变量 我几天前遇到过,我想你可以从那里找到if/el

我遇到了一个问题: 不知道答案是否是:

原因与类型系统有关。C/C++实际上不支持字符串作为类型。它确实支持常量字符数组的概念,但它并没有真正完全理解字符串的概念

即使使用C++11/14中的
std:string
,仍然适用。有没有一种方法可以代替几个
,如果(…)
,它仍然有效。
如上所述,条件可以是:

整数或枚举类型的任何表达式,或上下文可隐式转换为整数或枚举类型的类类型的任何表达式,或使用大括号或equals初始值设定项声明此类类型的单个非数组变量

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

如果是(…)的话,有没有其他的选择

您可以编写自己的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)
  );

}
#包括
#包括
#包括
#包括
//就我们是否分手发表意见
//使宏看起来更像switch语句
#定义“断开真值”
//外部函数使用的模板详细信息
名称空间开关\u impl{
//表示案例语句
模板
结构Case_语句{
U值;
T表达;
布尔休息;
Case_语句(U值,T表达式,bool breaks=false)
:值(value)
,表达式(表达式)
,休息(休息)
{}
};
//递归模板解包以类似于switch语句的方式进行计算
模板
内联类型名称std::enable_if::type
评估(C比较器、布尔发现、标准::元组和t)
{ }
模板
内联类型名称std::enable_if::type
评估(C比较器、布尔发现、标准::元组和t)
{
if(std::get(t).value==comparator | | found){
std::get(t).expression();
如果(!std::get(t).breaks){
评估(比较器,真,t);
}
}否则{
评估(比较,假,t);
}
}
}
//要组合的基函数,使其看起来像switch语句
模板
无效开关(T比较器、语句…语句)
{
自动t=std::生成元组(语句;
开关_impl::evaluate(比较器,false,t);
}
模板
自动大小写(U值,T表达式,bool breaks=false)->switch\U impl::Case\U语句{
返回switch_impl::Case_语句(值、表达式、断点);
}
//示例用法
int main(){
//c样式开关示例:
开关(2){
案例1:

std::cout另一种选择是将字符串映射到std::function,但如果需要使用默认大小写,则这种映射非常困难

#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");;
}
#包括
#包括
#包括
#包括
使用名称空间std;
静态常量映射处理程序{

{“AAPL”,[](const auto&str){coutc#在内部执行的方式是它获取字符串的哈希代码并打开它。

这是相当标准的。std::string是c++98/03A解决方案的一部分:您可以使用它编写哈希函数,如
“some\u string”_散列
,因此最终的代码看起来会很好。即使为字符串上的
开关
添加语言支持,编译器也不太可能对一系列
if
语句执行任何不同的操作。而且我不认为
开关
块比序列更可读
if
语句的哈希值。因此,我并不认为这有什么好处。@vsoftco-虽然它不是完全可靠的,但在实践中很少,理论上可以为不同的字符串获得相同的哈希值。比其他一系列ifs:)@ddriver“丑陋”更丑陋、更冗长是主观的。对于使用开关的人来说,我看不出它有多冗长:
if(value==“1”){…}
Case(“1”,[&](){…}短不了多少
。整个模板魔术只编写一次,并隐藏在头文件/模块单元中。不同之处在于,此处显示的此解决方案更好地显示了目的:您希望根据一个值做一些不同的事情,而不是依赖于在彻底阅读后可能与开关大小写相同的其他IF的任意序列ngI不太明白你的代码是怎么做的。如果经常需要“case开关”,那么肯定有一个解决方案。