打开包装清单

Kor*_*icz 7 c++ templates variadic-templates c++14 c++17

假设我有一个只接受类型模板参数的函数,我无法改变它的定义/实现.

template < typename T >
void do_it();
Run Code Online (Sandbox Code Playgroud)

现在我有一个通常的方式定义的类型列表,也不能改变它:

template< typename ...Ts >
struct typelist;
Run Code Online (Sandbox Code Playgroud)

我想实现一个带有类型列表的函数,并在每个类型上运行do_it():

template< typename List >
void do_them();
Run Code Online (Sandbox Code Playgroud)

我找到的唯一解决办法是:

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{} ); 
}
Run Code Online (Sandbox Code Playgroud)

但是对于我想要创建单个do_them函数的每种情况,这需要4个(!)函数.我将需要其中的一些,我不想为每个函数编写四个函数.我错过了什么吗?

C++ 14欢迎,C++ 17解决方案,但标记为这样.

Tar*_*ama 7

在C++ 14中,您可以使用一些可怕的技巧来引入有效的包扩展上下文:

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{} ); 
}
Run Code Online (Sandbox Code Playgroud)

这允许您避免递归模板实例化,这通常更昂贵.

现场演示


在C++ 17中,您可以使用折叠表达式:

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{} ); 
}
Run Code Online (Sandbox Code Playgroud)

现场演示