问题
I want to switch over possible values of two integers, or in another case two bools. For the sake of discussion, suppose I've done
auto mypair = std::make_pair(foo, bar);
How can I achieve the equivalent of
switch(mypair) {
case make_pair(true, false): cout << "true and false"; break;
case make_pair(false, true) cout << "false and true"; break;
case default: cout << "something else";
}
with C++11? (C++14/17 also relevant if that helps)?
回答1:
C++'s switch statement doesn't have the pattern matching power of many other languages. You'll need to take a slightly different approach.
Here's a possibility I threw together:
pair_switch(my_pair,
std::make_tuple(true, false, []{ std::cout << "true and false"; }),
std::make_tuple(false, true, []{ std::cout << "false and true"; }));
You supply a std::pair<bool,bool>
and a set of cases as std::tuples
, where the first two elements match the pair you pass in and the third element is a function to call for that case.
The implementation has a few template tricks, but should be pretty usable:
template <typename... Ts>
void pair_switch(std::pair<bool,bool> pair, Ts&&... ts) {
//A table for the cases
std::array<std::function<void()>, 4> table {};
//Fill in the cases
(void)std::initializer_list<int> {
(table[std::get<0>(ts)*2 + std::get<1>(ts)] = std::get<2>(ts), 0)...
};
//Get the function to call out of the table
auto& func = table[pair.first*2 + pair.second];
//If there is a function there, call it
if (func) {
func();
//Otherwise, throw an exception
} else {
throw std::runtime_error("No such case");
}
}
Live Demo
回答2:
You can only switch on an integral type, but if you can devise a function to map your pair (or any complex type) to an integral type, you can declare it as constexpr
(C++11) to indicate it can be resolved at compile time. Then it is acceptable as a case expression.
Simple example:
enum Action { peel, eat, juice };
enum Fruit { apple, orange, banana };
constexpr unsigned int switch_pair(Action a, Fruit f) {
return (a << 16) + f;
}
Then define the switch like this:
switch(switch_pair(mypair.first,mypair.second))
{
case switch_pair(peel,apple): std::cout << "Peeling an apple" << std::endl; break;
case switch_pair(eat,apple): std::cout << "Eating an apple" << std::endl; break;
case switch_pair(juice,apple): std::cout << "Juicing an apple" << std::endl; break;
default:
throw std::runtime_error("We only have apples!");
}
来源:https://stackoverflow.com/questions/35359004/switch-statement-for-an-stdpair