C ++开关 - 预处理的案例参数?

时间:2012-05-26 11:16:57

标签: c++ switch-statement c-preprocessor

在我的开关中,我希望案例从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++。那么可能是枚举,还是一些不错的宏功能?

EDIT 感谢if-else提示,我只是认为,因为案例值是已知的编译时间,所以使用开关会更好..

并指定我想要做的事情:我有一个菜单char[rows][cols]={"first line","second line"}。我想将开关案例映射到行,这样如果我想从菜单中删除一行(减少后面的行号),我将在程序的其余部分删除一个案例。

5 个答案:

答案 0 :(得分:1)

一系列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');
 }

答案 1 :(得分:1)

这可能很愚蠢,但你考虑过这样的事情:

#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

答案 2 :(得分:1)

预处理器中没有状态保持结构。但是,在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

现在,每次从中间移除案例时,您的数组索引都会自动“重新编号”。

答案 3 :(得分:0)

我不完全明白你想做什么,但显然你不应该使用switch;它并不意味着你想要实现的逻辑。

您可能会改为使用一系列if(...) else if (...)语句。

答案 4 :(得分:0)

我认为Boost Preprocessor库提供了在编译时生成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,并且必须在编译行中包含-DBOOST_PP_VARIADICS。