C++开关-经过预处理的大小写参数

C++ switch - preprocessed case arguments?

本文关键字:大小写 参数 预处理 经过 开关 C++      更新时间:2023-10-16

在我的开关中,我希望大小写从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。