C++ 是否给出了“的答案?”;为什么不能对字符串应用switch语句;即使使用C++;11/14?
我遇到了一个问题: 不知道答案是否是: 原因与类型系统有关。C/C++实际上不支持字符串作为类型。它确实支持常量字符数组的概念,但它并没有真正完全理解字符串的概念 即使使用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
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开关”,那么肯定有一个解决方案。