Lets say I have a function that takes just a type template parameter, I cannot change it's definition/implementation.
template < typename T >
void do_it();
Now I have a typelist defined a usual way, can't change it either:
template< typename ...Ts >
struct typelist;
I want to implement a function that takes a typelist, and runs do_it() on every type:
template< typename List >
void do_them();
The only solution I found up 'till now is:
template< typename T >
void do_them_impl()
{
do_it<T>();
}
template< typename T, typename Ts...>
void do_them_impl()
{
do_it<T>();
do_them_impl<Ts...>();
}
template< template < typename...> class List, typename ...Ts >
void do_them_extract( List<Ts...>&& )
{
do_them_impl< Ts >();
}
template< typename List >
void do_them()
{
do_them_impl( List{} );
}
But that requires 4(!) functions for each case I want to create a single do_them
function. I will require quite a few of those, and I don't want to write a quad of functions for each. Am I missing something?
C++14 welcome, C++17 solutions too, but marked as such.
In C++14 you can use some awful tricks to introduce a valid pack expansion context:
template< template < typename...> class List, typename ...Ts >
void do_them_impl( List<Ts...>&& )
{
(void)std::initializer_list<int> {
(do_it<Ts>(), 0)...
};
}
template< typename List >
void do_them()
{
do_them_impl( List{} );
}
This allows you to avoid recursive template instantiation, which is generally more expensive.
Live Demo
In C++17 you can use fold expressions:
template< template < typename...> class List, typename ...Ts >
void do_them_impl( List<Ts...>&& )
{
(do_it<Ts>(), ...);
}
template< typename List >
void do_them()
{
do_them_impl( List{} );
}
Live Demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With