Search code examples
c++c++17template-meta-programmingtemplate-argument-deductiontemplate-templates

Deduction guide to extract template template from types


Consider the following class:

// Class definition
template <template <class...> class... Templates>
class template_pack
{
    public:
    template <class... Types>
    constexpr template_pack(const Types&...) noexcept;
};

// Class template argument deduction guide
template <class... Types>
template_pack(const Types&...) -> template_pack</* something here */>

We suppose that the Types... are of the form template <class...> class... Templates. What I would like is:

template_pack pack(std::vector<int>{}, std::list<double>{}, std::deque<char>{});

to lead to:

template_pack<std::vector, std::list, std::deque>;

How to make that work?


Solution

  • I "succeed" with additional traits:

    template <typename T> struct template_traits;
    
    // Variadic case
    template <template <class...> class C, typename ... Ts>
    struct template_traits<C<Ts...>>
    {
        template <typename ... Us>
        using template_type = C<Us...>;
    };
    

    And then, argument deduction is:

    // Class template argument deduction guide
    template <class... Types>
    template_pack(Types&&...)
    -> template_pack<template_traits<std::decay_t<Types>>::template template_type...>;
    

    Demo

    Issue is that aliases are not really identical (gcc considers some aliases as identical contrary to clang) (I opened a question for that BTW)

    template_traits<std::vector>::template_type is not std::vector even if for any T, A, template_traits<std::vector>::template_type<T, A> is not std::vector<T, A>.