# Creating my own flow control statements in C++. Is that acceptable?

I always considered switch statement as somehow defective:

• works only on integral types and enumerations.
• forget a break - you have a bug.
• variable declaration spills over neighbouring cases.
• is essentially a computed goto

Because of said reasons, and also as an exercise on lambdas and variadic templates I created my own flow control function.

#include <functional>
#include <tuple>

template<typename V>
bool switch_on(const V& value)
{
return false;
}

template<typename V, typename P, typename... Args>
bool switch_on(const V& value, const P& p, Args... args)
{
if(std::get<0>(p)(value, std::get<1>(p)))
{
std::get<2>(p)();
return true;
}
else
{
return switch_on(value, args...);
}
}

template<template <typename> class P, typename F, typename V >
auto case_of(const V& v, const F& p) -> decltype( std::make_tuple(P<V>(), v, p) )
{
return std::make_tuple(P<V>(), v, p);
}

template<typename P, typename F, typename V >
auto case_of(const V& v, const F& p) -> decltype( std::make_tuple(P(), v, p) )
{
return std::make_tuple(P(), v, p);
}

template<typename F, typename V >
auto case_of(const V& v, const F& p) -> decltype( std::make_tuple(std::equal_to<V>(), v, p) )
{
return std::make_tuple(std::equal_to<V>(), v, p);
}


so I can use:

using std::less;
using std::greater;

int main()
{
int a = 42;
switch_on(a,
case_of<less>(0, [&]{
std::cout << "LESS THAN ZEROOOOOOOOOOOOOO.";
}),
case_of(42, [&]{
std::cout << "Yes";
}),
case_of<greater>(9000, [&]{
std::cout << "IT'S OVER NINE THOUSAAAAAAAAND!!!";
})
);
}


While in Lisp, it is encouraged to create new forms of flow control, what about C++? I would also like to see some opinions about template usage, some pointers on how to improve the code and possible corner cases when this code will break.

• Not sure I agree wiht: isn't an readability improvement over traditional if/else chain. or forget a break - you have a bug lot of functionality for fall through and when you do need it the compiler will warn you about it being missing so not a real problem. Don't believe this is true variable declaration spills over neighboring cases in C++. Anything with a constructor is bound into a case scope. Though true is essentially a computed goto you can use the same argument for for(;;), while(), if(){}else{} etc. Any control flow basically boils down to a computed goto. – Martin York Jun 5 '13 at 0:58
• @LokiAstari when you do need it the compiler will warn you about it being missing so not a real problem. Not sure what you mean here - can compiler distinguish when I need fall-through? Anything with a constructor is bound into a case scope. Well, apparently only if you use braces to introduce one, that is, by is essentially a computed goto I meant goto not on assembler level, but on a high-level language level. And the rant against break is because switch favours less common case (I want to fall-throgh) over more common case. – milleniumbug Jun 5 '13 at 1:41
• @LokiAstari I realise that my approach is flawed though - this function doesn't integrate so well with language, but I'm still looking for alternatives. – milleniumbug Jun 5 '13 at 1:46

• Thank you for your opinion. Well, at first I tried to copy Pascal's case of statement, and halfway switched to VB's Select Case. So... yeah, maybe it's not that readable. – milleniumbug Jun 4 '13 at 14:03