Skip to content

Instantly share code, notes, and snippets.

@christopherschwaab
Created September 1, 2012 10:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save christopherschwaab/3569535 to your computer and use it in GitHub Desktop.
Save christopherschwaab/3569535 to your computer and use it in GitHub Desktop.
Generating Switch Statements in C++
/* Copyright (C) 2012 Christopher Schwaab
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdio.h>
#include <switch.hpp>
enum { ADD = 0, SUB = 1, MUL = 2, DIV = 3, MOD = 4 };
template <int Operation>
struct interpreter {
static inline int run(const int x, const int y);
};
template <> struct interpreter<ADD> {
static const char *name() { return "ADD"; }
static inline int run(const int x, const int y)
{ return x + y; }
};
template <> struct interpreter<SUB> {
static const char *name() { return "SUB"; }
static inline int run(const int x, const int y)
{ return x - y; }
};
template <> struct interpreter<MUL> {
static const char *name() { return "MUL"; }
static inline int run(const int x, const int y)
{ return x * y; }
};
template <> struct interpreter<DIV> {
static const char *name() { return "DIV"; }
static inline int run(const int x, const int y)
{ return x / y; }
};
template <> struct interpreter<MOD> {
static const char *name() { return "MOD"; }
static inline int run(const int x, const int y)
{ return x % y; }
};
template <int Operation>
struct operation_table {
static always_inline int value(const bool printResult, const int x, const int y) {
const int r = interpreter<Operation>::run(x, y);
if (printResult) printf("operation_table<%s>::run(%i, %i) = %i\n",
interpreter<Operation>::name(), x, y, r);
return r;
}
};
int main() {
int(*operations[])(const bool,const int,const int) = {
operation_table<ADD>::value, operation_table<SUB>::value,
operation_table<MUL>::value, operation_table<DIV>::value,
operation_table<MOD>::value
};
bool printResult = true;
int op,x,y;
printf("op,x,y: ");
scanf("%i,%i,%i", &op, &x, &y);
metalevel::switch_table<ADD, MOD, operation_table>::run<int>(op,printResult,
x,y);
operations[op](printResult,x,y);
return 0;
}
/* Copyright (C) 2012 Christopher Schwaab
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef _metalevel_switch_h_
#define _metalevel_switch_h_
#include <boost/mpl/at.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/list.hpp>
#include <boost/mpl/pair.hpp>
#include <boost/mpl/push_front.hpp>
#include <boost/mpl/size.hpp>
#include <boost/preprocessor/iterate.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#ifdef __GNUC__
# define always_inline __attribute__((always_inline))
#elif defined(_MSC_VER)
# define always_inline __forceinline
#else
# define always_inline inline
#endif
#ifndef METALEVEL_MAX_CHOICE_ARGS
# define METALEVEL_MAX_CHOICE_ARGS 20
#endif
#ifndef METALEVEL_MAX_SWITCH_SIZE
# define METALEVEL_MAX_SWITCH_SIZE 20
#endif
namespace metalevel {
namespace aux {
template <int NumberOfCases, typename Xs>
struct switch_impl;
# define BOOST_PP_ITERATION_LIMITS (0, METALEVEL_MAX_SWITCH_SIZE)
# define BOOST_PP_FILENAME_1 <switch_impl.hpp>
# include BOOST_PP_ITERATE()
template <int Counter, int N, template <int> class Table>
struct tabulate
: boost::mpl::push_front<
tabulate<Counter-1, N-1, Table>,
boost::mpl::pair<boost::mpl::int_<N>, Table<N> >
>::type {};
template <int N, template <int> class Table>
struct tabulate<0, N, Table>
: boost::mpl::list<
boost::mpl::pair<boost::mpl::int_<N>, Table<N> >
> {};
} // namespace aux
template <typename Xs>
struct switch_
: aux::switch_impl<boost::mpl::size<Xs>::type::value - 1, Xs> {};
template <int Lower, int Upper, template <int> class Table>
struct switch_table
: switch_<aux::tabulate<Upper - Lower + 1, Upper, Table> > {};
} // namespace metalevel
#endifs
/* Copyright (C) 2012 Christopher Schwaab
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifdef BOOST_PP_IS_ITERATING
#define NUMBER_OF_CASES BOOST_PP_FRAME_ITERATION(1)
template <typename Xs>
struct switch_impl<NUMBER_OF_CASES, Xs> {
# define TYPEDEF_X_SUB_I(_, i, __) \
typedef typename boost::mpl::at_c<Xs, i>::type x_##i;
BOOST_PP_REPEAT(NUMBER_OF_CASES, TYPEDEF_X_SUB_I, ~)
# define METALEVEL_CASE_TABLE_ENTRY(_, i, ts) \
case boost::mpl::first<x_##i>::type::value: \
return boost::mpl::second<x_##i>::type::value ts ;
# define DEFINE_CHOICE_RUN(_, argc, __) \
template <typename R BOOST_PP_COMMA_IF(argc) \
BOOST_PP_ENUM_PARAMS(argc, typename T)> \
static always_inline R \
run(int n BOOST_PP_COMMA_IF(argc) \
BOOST_PP_ENUM_BINARY_PARAMS(argc, T, t)) { \
switch(n) { \
BOOST_PP_REPEAT(NUMBER_OF_CASES, \
METALEVEL_CASE_TABLE_ENTRY, \
(BOOST_PP_ENUM_PARAMS(argc, t))) \
} \
}
BOOST_PP_REPEAT(METALEVEL_MAX_CHOICE_ARGS,
DEFINE_CHOICE_RUN, ~)
# undef DEFINE_CHOICE_RUN
# undef METALEVEL_CASE_TABLE_ENTRY
};
#undef NUMBER_OF_CASES
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment