Reputation: 2287
I would like to specialize an template class with variadic template template parameter by non-template class. Please see below.
// non-template base class
class BaseNoneTemplate {
public:
void print(void) {
std::cout << "BaseNoneTemplate" << std::endl;
}
};
// template base class
template <typename T>
class BaseTemplate {
public:
void print(void) {
std::cout << "BaseTemplate" << std::endl;
}
};
// primary template class
template <template <typename...> class T_Self, typename... T_Params>
class VariadicTemplate : public T_Self<T_Params...> {
public:
VariadicTemplate() = default;
virtual ~VariadicTemplate() = default;
void print(void) {
this->T_Self<T_Params...>::print();
}
};
// specialized class with a non-template class
// ********** This specialized class makes an error: see the error message at the end of this question ***********
template <>
class VariadicTemplate<BaseNoneTemplate> : public BaseNoneTemplate {
public:
VariadicTemplate() = default;
virtual ~VariadicTemplate() = default;
void print(void) {
this->BaseNoneTemplate::print();
}
};
// specialized class with an template class
// ***** This class is an ok example *****
template <typename T_Value>
class VariadicTemplate<BaseTemplate, T_Value> : public BaseTemplate<T_Value> {
public:
VariadicTemplate() = default;
virtual ~VariadicTemplate() = default;
void print(void) {
this->BaseTemplate<T_Value>::print();
}
};
void test_variadic_template(void) {
VariadicTemplate<BaseNoneTemplate> non_template;
VariadicTemplate<BaseTemplate, int> an_template;
non_template.print();
an_template.print();
}
In the code above, I could not specialize an template class with variadic template template parameter by non-template class, BaseNoneTemplate. Does someone knows how to specialize it with non-template class?
The error by compiler is following,
../template_template_variadic.hpp:44:40: error: type/value mismatch at argument 1 in template parameter list for ‘template<template<class ...> class T_Self, class ... T_Params> class VariadicTemplate’ class VariadicTemplate<BaseNoneTemplate> : public BaseNoneTemplate {
^
../template_template_variadic.hpp:44:40: note: expected a class template, got ‘BaseNoneTemplate’
Thank you very much.
Upvotes: 2
Views: 114
Reputation: 218278
If your VariadicTemplate
expects template <typename...> class, typename...
as template argument, you cannot specialize it for type.
What you can do is to expect type and specialize for specific type or (partial) specialize for types which come from template types.
template <typename T> class VariadicTemplate;
// Partial specialization
template <template <typename...> class C, typename... Ts>
class VariadicTemplate<C<Ts...>> : public C<Ts...> {
public:
void print() { C<Ts...>::print(); };
// or using C<Ts...>::print;
};
// Full specialization
template <>
class VariadicTemplate<BaseNoneTemplate> : public BaseNoneTemplate {
public:
void print() { BaseNoneTemplate::print(); };
// or using BaseNoneTemplate::print;
};
Upvotes: 1
Reputation: 13718
How about adding another layer of generalization?
//...
template <typename... Types>
class VariadicTemplate;
// primary template class
template <template <typename...> class T_Self, typename... T_Params>
class VariadicTemplate<T_Self<T_Params...>, T_Params...>: public T_Self<T_Params...> {
//...
};
//...
void test_variadic_template(void) {
VariadicTemplate<BaseNoneTemplate> non_template;
VariadicTemplate<BaseTemplate<int>, int> an_template;
non_template.print();
an_template.print();
}
I've removed parts I didn't change. This code doesn't compile on MSVC2015, though for the reason unknown. I've filed a bug but if you are using it then it won't help you any time soon.
This version works on MSVC(besides being more concise and clean):
template <typename... Types>
class VariadicTemplate;
//..
template <template <typename...> class T_Self, typename... T_Params>
class VariadicTemplate<T_Self<T_Params...>>: public T_Self<T_Params...> {
//...
}
//...
void test_variadic_template(void) {
VariadicTemplate<BaseNoneTemplate> non_template;
VariadicTemplate<BaseTemplate<int>> an_template;
non_template.print();
an_template.print();
}
Upvotes: 1