Suppose I have a std::tuple
made up of types like
struct A {
static void tip();
};
struct B {
static void tip();
};
struct Z {
};
std::tuple<const A&,const B&,const Z&> tpl;
Yes, I need separate A
, B
. (The implementation of ::tip()
differs for each type.) What I try to implement is a type-sensitive "visitor" that iterates through the tuple starting from the beginning to the end. Upon visiting a particular element of type T
a function should be called depending on whether T
has the ::tip()
method or not. In the simple example of above only A
and B
have ::tip()
implemented and Z
not. So, the iterator should call twice the function for types with the ::tip()
method and once the other function.
Here is what I came up with:
template< int N , bool end >
struct TupleIter
{
template< typename T , typename... Ts >
typename std::enable_if< std::is_function< typename T::tip >::value , void >::type
static Iter( const T& dummy , const std::tuple<Ts...>& tpl ) {
std::cout << "tip\n";
std::get<N>(tpl); // do the work
TupleIter<N+1,sizeof...(Ts) == N+1>::Iter( std::get<N+1>(tpl) , tpl );
}
template< typename T , typename... Ts >
typename std::enable_if< ! std::is_function< typename T::tip >::value , void >::type
static Iter( const T& dummy , const std::tuple<Ts...>& tpl ) {
std::cout << "no tip\n";
std::get<N>(tpl); // do the work
TupleIter<N+1,sizeof...(Ts) == N+1>::Iter( std::get<N+1>(tpl) , tpl );
}
};
template< int N >
struct TupleIter<N,true>
{
template< typename T , typename... Ts >
static void Iter( const std::tuple<Ts...>& tpl ) {
std::cout << "end\n";
}
};
I use a dummy
instance of the type of the element at the iterator position and decide via enable_if
which function to call. Unfortunately this doesn't work/isn't a nice solution:
- The compiler complains about recursive instantiation
- The
const T& dummy
is not a clean solution
I was wondering if enable_if
is the right strategy to do the decision and how can one recursively iterate through the std::tuple
capturing the first type and keeping all the remaining arguments in vital state. Read through How to split a tuple? but it doesn't do any decision.
How can one implement such a thing in a correct and portable way in C++11?