Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expanding a parameter pack of template<class>classes

Suppose I have some template classes defined as follows

template<template<class>class...>
struct my_class;

template<class>
struct define_template{
    template<class>
    class type;
};

I need to define an alias template that substitutes define_template::type into my_class so for three classes I could do this

template<class A, class B, class C>
using my_alias = my_class<  define_template<A>::template type, 
                            define_template<B>::template type, 
                            define_template<C>::template type>;

I can't work out the syntax to do this for a variadic template ideally something like this

template<class... T>
using new_class = my_class<define_template<T>::template type...>;

which gives me an error "parameter packs not expanded with '...'

Does anybody know the correct synax?

From the comments below it compiles in clang, I'm using gcc 4.8.2 through Cygwin.

like image 764
Tim Avatar asked Oct 22 '14 13:10

Tim


1 Answers

I'm assuming it's a bug in gcc so I've done a workaround for now

// partially specializes a template
template<template<class, class>class TT, class T>
struct TemplateBind{
    template<class S>
    using type = TT<T, S>;
};


// the workaround
template<template<template<class>class...>class A,
         template<class, class>class B,
         template<class>class... C>
class workaround {
    template<class D, class... E>
    static auto get_type(D, E...)
    -> typename workaround<A, B, C..., TemplateBind<B, D>::template type>::template type<E...>;

    static auto get_type()
    ->A<C...>;

public:
    template<class... T>
    using type = decltype(get_type(std::declval<T>()...));

};

// convinience alias
template<template<template<class>class...>class OriginalTemplate,
         template<class, class>class Substitution,
         class... Types>
using InstatiateVariadicTemplateTemplate = typename workaround<OriginalTemplate, Substitution>::template type<Types...>;

Then we can define a wrapper for define_template

// wrapper alias gets  define_template in the right form
template<class A, class B>
using my_wrapper = typename define_template<A>::template type<B>;

and instantiate as follows

template<class... T>
using my_alias = InstatiateVariadicTemplateTemplate<my_class, my_wrapper, T...>;
like image 85
Tim Avatar answered Oct 31 '22 16:10

Tim