C++开关-经过预处理的大小写参数
C++ switch - preprocessed case arguments?
在我的开关中,我希望大小写从0到(number_of_cases-1
(,而不需要自己写数字。因此,如果我删除中间的一个案例块,下面的案例将重新编号(递减1(,因此切换再次从(0..caseNo-1
(开始。
像这样(当然它不会编译,因为i++
不知道编译时间(:
#include <iostream>
#define ALWAYS_SECOND_CASE 1
void nop(char c){}
int main()
{
int i=0;
int var=ALWAYS_SECOND_CASE;
switch(var)
{
case i++: //case 0:
nop('x');
break;
case i++: //case 1:
nop('y')
break;
case i++: //case 2:
nop('z')
break;
}
//case 1 should have been switched to, nop('y') called.
}
现在我删除了中间的案例,并且没有写任何东西,最后一个案例应该从案例2变成案例1:
#include <iostream>
#define ALWAYS_SECOND_CASE 1
void nop(char c){}
int main()
{
int i=0;
int var=ALWAYS_SECOND_CASE;
switch(var)
{
case i++: //case 0:
nop('x');
break;
case i++: //case 1: instead of case 2 like before
nop('z')
break;
}
//case 1 should have been switched to, nop('z') called,
// instead of nop('y') like before.
}
所以我不能使用变量,因为它们太多变了;那么符号常数太恒定了,我可以做SYMC+1
,但不能做SYMC++
。也许是枚举,或者一些不错的宏函数?
编辑感谢if-else的提示,我只是觉得既然case值在编译时是已知的,那么使用开关会更好。。
为了指定我想做什么:我有一个菜单char[rows][cols]={"first line","second line"}
。我想将开关大小写映射到行,这样,如果我想从菜单中删除一行(按行号递减(,我只会在程序的其余部分删除一个大小写。
预处理器中没有状态保持结构。然而,在C++11中,您可以使用lambdas来表达各个事例,将它们放在一个数组中,并以类似于switch
的方式使用,每个事例后都有中断:
function<void()> cases[] = {
[] () {cout << "quick" << endl; }
, [] () {cout << "brown" << endl; }
, [] () {cout << "fox" << endl; }
};
int k = 1;
cases[k](); // <<== This is where the switch happens
现在,每次从中间删除一个大小写时,数组索引都会自动"重新编号"。
一系列if
语句怎么样?
int i=0;
int var=ALWAYS_SECOND_CASE;
if (var == i++) {
nop('x');
} else if (var == i++) {
nop('y');
} else if (var == i++) {
nop('z');
}
这可能很傻,但你有没有考虑过这样的东西:
#define ALWAYS_SECOND_CASE 1
std::string some_cases = "xyz";
nop(some_cases[ALWAYS_SECOND_CASE]);
std::string some_other_cases = "xz";
nop(some_other_cases[ALWAYS_SECOND_CASE]);
std::map
也在脑海中浮现。
我不完全理解您想要做什么,但很明显,您根本不应该使用switch
;它并不适用于您试图实现的逻辑。
您可能会使用一系列if(...) else if (...)
语句。
我认为Boost预处理器库提供了在编译时生成switch语句所需的宏。我没有访问编译器的权限来检查下面的代码,但如果它没有编译,它应该非常接近于可以解决你的问题的东西。
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/preprocessor/tuple/size.hpp>
#include <boost/preprocessor/repetition/for.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/comparison/not_equal.hpp>
#define OPS (x, y, z)
#define NOPS BOOST_PP_TUPLE_SIZE(OPS)
#define PRED(r, state) BOOST_PP_NOT_EQUAL(
BOOST_PP_TUPLE_ELEM(2, 0, state)
, BOOST_PP_TUPLE_ELEM(2, 1, state)
)
#define OP(r, state) (
BOOST_PP_INC(BOOST_PP_TUPLE_ELEM(2, 0, state))
, BOOST_PP_TUPLE_ELEM(2, 1, state)
)
#define MACRO(r, state)
case BOOST_PP_TUPLE_ELEM(2, 0, state):
BOOST_PP_TUPLE_ELEM(NOPS, BOOST_PP_TUPLE_ELEM(2, 0, state), OPS)();
break;
void x() { }
void y() { }
void z() { }
main() {
int i = 0;
switch(i) {
BOOST_PP_FOR((0, NOPS), PRED, OP, MACRO)
}
}
每当您想添加或删除操作时,只需修改OPS的定义,大小写值就会自动重新编号。我知道有些人不喜欢使用预处理器,但它能做的一些事情非常神奇。
更新:我再次访问了一个编译,我验证了上面的代码是否像广告中所说的那样工作。但是,它需要Boost 1.49,并且必须在编译行中包含-DBOOT_PP_VARIADICS。
- 如何反转整数参数包
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用默认参数等选择模板专业化
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 函数调用中参数的顺序重要吗
- 部分定义/别名模板模板参数
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- 使用不带参数的函数访问结构元素
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 如何使用Luacneneneba API正确读取字符串和表参数
- 在派生函数中指定void*参数
- 视图中的参数推导失败:take_while
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- 使用指向成员的指针将成员函数作为参数传递
- C++开关-经过预处理的大小写参数
- 使用字符串参数切换大小写