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