If you can set a limit to how big a bitset size you can use, you can cheat.
// invokes target<i>{}() if i >= min and i < max
template<template<size_t>class target, size_t max, size_t min=0>
struct magic_switch {
void operator()( size_t i ) const {
constexpr size_t mid = (min+max-1)/2;
if (i==max-1) target<max-1>{}();
else if(i<mid) magic_switch<target, mid,min>{}(i);
else magic_switch<target, max-1,mid>{}(i);
}
};
template<template<size_t>class target, size_t min>
struct magic_switch<target, min, min> {
void operator()( size_t i ) const {} // do nothing
};
int number;
template<size_t len>
struct program {
template<size_t number>
struct p2 {
void operator()() const {
std::bitset<len> arr[number];
// code
}
};
void operator()() const {
magic_switch<p2, 1001, 1>{}(number);
}
};
int main(int argc, char const* argv[]) {
int len;
if ( argc == 3 )
{
len = atoi(argv[1]);
number = atoi(argv[2]);
}
magic_switch<program, 1001, 1>{}( len );
}
of course, this approach is completely nuts and a bad idea.
Basically I created 10000000 programs, one for each len x number, then did a massive chained if to figure out which one to run.
This can be made more performant by storing pointers to the programs in an array, then doing an array lookup instead of a 20-deep recursion. It is still a bad idea.
Do not use this solution. If you don't understand why you shouldn't use it, then trust me. If you do understand why you shouldn't use it, then this paragraph is redundant.
A faster magic_switch (some compilers won't like it, and uses C++14 features):
template<template<size_t>class target, size_t max, size_t min=0>
struct magic_switch {
template<size_t...Is>
void operator()( std::index_sequence<Is...>, size_t i ) {
using task = void(*)();
static const task arr[] = {
[]{ target<min+Is>{}(); }...
};
arr[i-min]();
}
void operator()( size_t i ) const {
(*this)( std::make_index_sequence<max-min>{}, i );
}
};
here we build a jump table (in a static const array), do a lookup, and execute it.
Extending this to take/return args is relatively easy:
template<class Sig, template<size_t>class target, size_t max, size_t min=0>
struct magic_switch;
template<class R, class...Args, template<size_t>class target, size_t max, size_t min>
struct magic_switch<R(Args...), target, max, min> {
template<size_t...Is>
R operator()( std::index_sequence<Is...>, size_t i, Args&&...args ) {
using task = R(*)(Args&&...);
static const task arr[] = {
[](Args&&...args)->R{
return target<min+Is>{}(std::forward<Args>(args)...);
}...
};
return arr[i-min](std::forward<Args>(args)...);
}
R operator()( size_t i, Args...args ) const {
return (*this)(
std::make_index_sequence<max-min>{},
i,
std::forward<Args>(args)...
);
}
};
Using this one will take away the requirement that the number variable be stored globally. As global variables are bad practice, this improves the code.