C ++宏可以计算switch语句中的情况吗?

时间:2014-04-01 20:39:42

标签: c++ algorithm macros c-preprocessor

我有许多不同的lambda,它们遍历参数列表并选择其中一些(使用开关)来执行操作。我想确保每个lambda找到它正在寻找的每个案例中的至少一个,并报告是否有任何案例没有被击中。我可以设置一个bool矢量来跟踪是否找到每个案例,但是我需要知道转换中案例的完整数量,看看我是否得到了所有案例并查看bool的索引。我真的喜欢将它集成到一般案例宏中,这样如果稍后添加案例而不更新计数,任何事情都不会中断。

Lambda示例:

#define OneCase ???

auto MysteryLambda = [](Parameters params) -> int
{
 //something to set the case count to 0, whatever it is

 for (auto param : params)
 {
  switch (param)
  {
   case First:
    OneCase; //case count + 1
    //do operation
    break;
   case Second:
    OneCase; //case count + 1
    //do operation
    break;
   case Third:
    OneCase; //case count + 1
    //do operation
    break;
  }
 }


 static const int cases = ???; //this would be 3

 std::cout << "The enum has " << cases << " cases." << std::endl;

 return cases;
};

然后lambda可以返回该const计数。这可能吗?

如果不可能,是否有另一种方法可以做到这一点?

4 个答案:

答案 0 :(得分:2)

这可能就是使用GCC / MSVC __COUNTER__宏的一方,尽管它会在switch语句本身周围带来大量的脚手架。一般来说,不,这是不可能的。听起来你想要一个map的lambda,而不是一个switch语句。

答案 1 :(得分:1)

好的,Sneftel的__COUNTER__建议是可行的!以下是我设法使其发挥作用的方式:

enum class Parameter //sample parameters, they don't have to be the same for each lambda
{
 First, Second, Third, Fourth
};

typedef std::vector<Parameter> Parameters;

void test()
{
 static const int startcases = __COUNTER__ + 1; //the initial state of counter when this lambda is pre-proced

 auto GetIndex = [](unsigned int counter) -> unsigned int //helper function, it takes __COUNTER__ from wherever it is called
 {
  return counter - startcases;
 };

 //Example lambda.  This isn't built to do anything useful at all.

 auto Example = [&GetIndex](Parameters parameters, std::vector<bool>& used) -> unsigned int
 {
  for (auto parameter : parameters)
  {
   switch (parameter) //only looking at First and Third
   {
   case Parameter::First:
    used[GetIndex(__COUNTER__)] = true;
    break;
   case Parameter::Third:
    used[GetIndex(__COUNTER__)] = true;
    break;
   }
  }

  static const unsigned int cases = __COUNTER__ - startcases; //this would be 2

  std::cout << "The enum has " << cases << " cases." << std::endl;

  return cases;
 };

 //Ok, time for a test!

 //Load out sample params, using VC++2012 so no init list on vectors. :(

 Parameters parameters; 
 parameters.push_back(Parameter::First);
 parameters.push_back(Parameter::Second);
 parameters.push_back(Parameter::First); //no Third in this vector
 parameters.push_back(Parameter::Fourth);

 std::vector<bool> used; //a vector of bools filled to some arbitrary capacity with falses, I can have size checks in a more extensive helper function so no big deal
 used.insert(used.begin(), 10, false);

 unsigned int cases = Example(parameters, used); //returns # of cases in this particular lambda

 for (unsigned int i = 0; i < cases; ++i) //loop through for each case and see if one is false (meaning it had no hit)
 {
  if (!used[i])
  {
   std::cerr << "Didn't process case " << i << "." << std::endl; 
  }
 }
}

输出:

The enum has 2 cases.
Didn't process case 1.

答案 2 :(得分:0)

创意:将switch变成一堆if语句,记录它们在数组中的存在。

序言:

#define BIG_ENOUGH 50     // Just needs to be bigger than the maximum enum value

#define BEGIN_DETECTED_SWITCH(x) \
{ \
    vector<bool> __has(BIG_ENOUGH, false); \
    vector<bool> __saw(BIG_ENOUGH, false); \
    auto __x(x); \
    { ;    // Dummy open brace to be consumed by first DETECTED_CASE()

#define END_DETECTED_SWITCH \
    } \
    for (int i = 0; i < BIG_ENOUGH; ++i) { \
        if (__has[i] && !__saw[i]) { \
            cout << "Didn't see any " << i << "'s!\n"; \
        } \
    } \
}

#define DETECTED_CASE(x) \
    } \
    __has[x] = true; \
    if (__x == (x)) { \
        __saw[x] = true;

现在将每个switch语句转换为:

BEGIN_DETECTED_SWITCH(someEnumVal)
    DETECTED_CASE(First)
        // Code for first
    DETECTED_CASE(Second)
        // Code for second
    DETECTED_CASE(Third)
        // Code for Third
END_DETECTED_SWITCH

您可以通过让END_DETECTED_SWITCH获取每个非触发case调用的lambda参数来略微概括它,而不是硬编码“反应”。

答案 3 :(得分:0)

如果每个案例的代码行数是固定的(无可否认是一个硬约束),答案是肯定的!

在切换前插入Begin= __LINE__;,在其后插入End= __LINE__;。以后任何时候,(End - Begin - Extra) / LinesPerCase都会给你答案:)