cpp-typelist icon indicating copy to clipboard operation
cpp-typelist copied to clipboard

Conversion operation slow to compile for longer lists N>=12

Open albi-k opened this issue 3 years ago • 0 comments

Hi, Thank you for a really neat and concise library.

I ran into an issue with compilation time when using the conversion to/to_tuple operator. The compilation time seems to grow exponentially and is noticed for lists beyond just a few elements.

I want to document that here and the workarounds I tried to inform anyone else running into the same thing but also to hopefully resolve the long compilation time issue without needing to resort to workarounds.

The problem code:

#include <string>

//List of 13 types
using types = tl::type_list<int, bool, long, int, bool, char, size_t, long, std::string, size_t, char, std::string, bool>;

//1. Using tl::to<>   (12s)
using tup = types::to_tuple;

At 13 elements this takes over 10s to compile. An extra element and it's 20.

Workaround 1:

//2. Using specialization (< 1s)
//Need to write one of these for each target type
template <typename... Args>
struct wrap_as_tuple;

template <typename... Args>
struct wrap_as_tuple<tl::type_list<Args...>>
{
    using type = std::tuple<Args...>;
};

template <typename... Args>
using wrap_as_tuple_t = typename wrap_as_tuple<Args...>::type;

using tup = wrap_as_tuple_t<types>;

This workaround is fast but it is not generic enough: you have to write one of these for every target type.

Workaround 2:

//3. Using this external helper template (< 1s)
//Works similarly to tl::to<> in terms of using a variadic template template parameters
//however is more general and somehow compiles faster
template<template<typename...> class, typename>
struct _apply_tmpl_args_of;

template<template<typename...> class OtherTmpl, template<typename...> class Tmpl, typename... Args>
struct _apply_tmpl_args_of<OtherTmpl, Tmpl<Args...>> 
{
    using type = OtherTmpl<Args...>;
};

template<template<typename...> class OtherTmpl, typename T>
using apply_tmpl_args_of_t = typename _apply_tmpl_args_of<OtherTmpl, T>::type;

using tup = apply_tmpl_args_of_t<std::tuple, types>;

This workaround is generic and also performs fast. What baffles me is that it is not fundamentally that different to tl::to<> in the sense that both use variadic template template parameters.

Any ideas on how to<> can integrate the above idea and preserve compilation speed? MyTypeList::to<> is nicer to write than the above.

Link with examples above: https://gcc.godbolt.org/z/6hYqc7Mv5

Thank you

albi-k avatar Dec 07 '22 15:12 albi-k