samedi 1 décembre 2018

Template parameter extraction and modification

I wrote the following class to extract the template parameters of a Base class and append to it the template parameters of a derived class at compile time :

template <typename...> struct derived_type_traits;

// specialization for the case when Base is not a template
template <typename Base> struct derived_type_traits<Base> {
    template <template<typename...> class Derived, typename... DerivedArgs>
    using type = Derived<DerivedArgs...>;
};

// specialization for the case when Base is a template
template <template <typename...> class Base, typename... BaseArgs> struct derived_type_traits<Base<BaseArgs...>> {
    template <template<typename...> class Derived, typename... DerivedArgs>
    using type = Derived<DerivedArgs..., BaseArgs...>;
};

I use it as part of a factory building blocks. With this traits class, I can construct a Derived from a set of template parameters and a Base class :

namespace A {
    class Base {};
    template <typename T>
    class Derived : public Base {};
    auto ptr = new typename derived_type_traits<Base>::type<Derived, int>();
}

namespace B {
    class Base {};
    template <typename T1, typename T2, typename T3>
    class Derived : public Base {};
    auto ptr = new typename derived_type_traits<Base>::type<Derived, int, double, std::string>();    
}

namespace C {
    template <typename T>
    class Base {};
    template <typename T1, typename T2, typename T3, typename T>
    class Derived : public Base<T> {};
    auto ptr = new typename derived_type_traits<Base<int>>::type<Derived, int, double, std::string>();  
}

However, it does not work for the following cases :

namespace D {
    template <typename T>
    class Base {};
    template <typename T1, typename T2, template <typename,typename> class T3, typename T>
    class Derived : public Base<T> {};
    template <typename T1, typename T2> struct Foo {};
    auto ptr = new typename derived_type_traits<Base<int>>::type<Derived, int, double, Foo>();
}

namespace E {
    template <typename U1, template <typename,typename> class U2>
    class Base {};
    template <typename T1, typename T2, typename T3, typename U1, template<typename,typename> class U2>
    class Derived : public Base<U1,U2> {};
    template <typename T1, typename T2> struct Foo {};
    auto ptr = new typename derived_type_traits<Base<int, Foo>>::type<Derived, int, double, std::string>();
}

The test code is here.

I know that this is related to the fact that a variadic template can not match a mix of types and template types.

Is there a solution or am I going the wrong way about it ? I can use up to C++14 (no C++17).

Aucun commentaire:

Enregistrer un commentaire