#include
#include
#include
#include
using namespace std;
struct SubAlgorithm1 { void operator ()
Yes. I call the technique the magic switch.
You create a std::tuple
of your algorithms. You ceate a template function that will be passed one of those algorithms.
You can add other arguments via perfect variardic forwarding if you want.
template
bool magic_switch( int n, Func&& f, std::tuple const & pick ) {
if( n==Max-1 ) {
f(std::get(pick));
return true;
} else {
return magic_switch( n, std::forward(f), pick );
}
}
In pseudo code. Specialize Max==0 to just return false, and you might have to make it a functor so you can partial specialize.
The passed in functor is annoying to write, as a downside.
Another variation is to use a meta-factory (well, a meta programming type factory? Maybe it is a meta-map. Well, whatever.)
#include
#include
#include
#include
#include
#include
#include
#include
// metaprogramming boilerplate:
templateclass Factory, typename SourceTuple>
struct tuple_map;
templateclass Factory, templateclass L, typename... SourceTypes>
struct tuple_map> {
typedef L< Factory... > type;
};
templateclass Factory, typename SourceTuple>
using MapTuple = typename tuple_map::type;
template struct seq {};
template
struct make_seq: make_seq {};
template
struct make_seq<0, s...> {
typedef seq type;
};
template
using MakeSeq = typename make_seq::type;
// neat little class that lets you type-erase the contents of a tuple,
// and turn it into a uniform array:
template
struct TupleToArray;
templateclass L, typename... Ts, typename DestType>
struct TupleToArray, DestType> {
template
std::array< DestType, sizeof...(Ts) > operator()( L const& src, seq ) const {
std::array< DestType, sizeof...(Ts) > retval{ DestType( std::get(src) )... };
return retval;
}
std::array< DestType, sizeof...(Ts) > operator()( L const& src ) const {
return (*this)( src, MakeSeq() );
}
};
template< typename DestType, typename SourceTuple >
auto DoTupleToArray( SourceTuple const& src )
-> decltype( TupleToArray()( src ) )
{
return TupleToArray()( src );
}
// Code from here on is actually specific to this problem:
struct SubAlgo { int operator()(int x) const { return x; } };
struct SubAlgo2 { int operator()(int x) const { return x+1; } };
template
struct FullAlgo {
void operator()( std::vector& v ) const {
for( auto& x:v )
x = Sub()( x );
}
};
// a bit messy, but I think I could clean it up:
typedef std::tuple< SubAlgo, SubAlgo2 > subAlgos;
MapTuple< FullAlgo, subAlgos > fullAlgos;
typedef std::function< void(std::vector&) > funcType;
std::array< funcType, 2 > fullAlgoArray =
DoTupleToArray< funcType >( fullAlgos );
int main() {
std::vector test{1,2,3};
fullAlgoArray[0]( test );
for (auto&& x: test)
std::cout << x;
std::cout << "\n";
fullAlgoArray[1]( test );
for (auto&& x: test)
std::cout << x;
std::cout << "\n";
}
which is lots of boilerplate, but what I've just done is allowed you to take your stateless sub algorithm and plug it into your full algorithm one element at a time, then type-erase the resulting full algorithm and store it in a std::function
array.
There is a virtual
call overhead, but it occurs at the top level.