Unpacking a typelist

夙愿已清 提交于 2019-12-05 04:45:42

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

Here is a solution that takes advantage of C++14's generic lambdas:

template <typename T>
struct type_ { using type = T; };

template <typename Type>
using type = typename Type::type;

template <typename List>
struct map_;

template <template <typename...> typename Container, typename... Ts>
struct map_<Container<Ts...>>
{
    template <typename Fun>
        void operator()(Fun&& fun)
        {
            (void)((int[sizeof...(Ts)]){(fun(type_<Ts>{}), 0)...});
        }
};

template <typename List>
auto map = map_<List>{};

Then for each function

#include <iostream>
#include <cxxabi.h>
#include <typeinfo>

template <typename T>
const char * type_name()
{
        return abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, nullptr);
}

template <typename T>
void do_it()
{
    std::cout << type_name<T>() << std::endl;
}

you can write:

template <typename List>
void do_them()
{
    map<List>([](auto v){ do_it<type<decltype(v)>>(); });
}

template <typename... Ts>
struct typelist {};

int main()
{
    do_them<typelist<int, char, bool>>();
    return 0;
}

Compiling with -O3 gives the same assembly as if we simply called do_it<int>, do_it<char>, do_it<bool> in succession.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!