我有许多不同的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计数。这可能吗?
如果不可能,是否有另一种方法可以做到这一点?
答案 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
都会给你答案:)