Параметры шаблона шаблона позволяют передавать шаблоны в другие шаблоны.Они не являются конкретными типами и должны быть параметризованы для их усиления.
В моем классе шаблонов для Bar, где он получает аргумент шаблона шаблона, что представляет <typename X>
?
Из стандартного [basic.scope.temp] ;
Декларативная область имени параметра шаблона шаблона-параметра шаблона является наименьшим списком параметров шаблона, в котором было введено имя.
Это в основном говорит, что имя доступно только в списке параметров шаблона этого шаблона.Во многих случаях достаточно просто указать typename
без имени для параметра шаблона шаблона, но имена могут служить для документирования вашего кода.
Однако пример, когда полезно дать ему имя, этоесли от него зависит другой параметр шаблона нетипичного типа.Для пример , template <template <typename X, X> typename Y>
.
Что касается вашего примера кода, у вас есть две проблемы со вторым объявлением Bar.Во-первых, Bar уже объявлен для принятия типа, а не шаблона.Ваше второе объявление вступает в противоречие, так как оно объявлено для принятия шаблона.
Здесь вам требуется специализация Bar, где специализация разрешается в один тип, соответствующий первичному шаблону.Например,
template <template <typename> class T,typename Y>
struct Bar<T<Y>> {
T<Y> data;
Bar() : data() { cout << "Bar" << endl; }
};
Здесь важно отметить, что параметры шаблона в специализации могут быть любыми.Это часть после struct Bar
, которая должна соответствовать первичному шаблону.Все параметры в специализации будут выведены из типа, переданного в качестве параметра шаблона, в ваш экземпляр Bar.
Ваша вторая проблема заключается в том, что вы объявляете член Bar типа T. T являетсяшаблон во втором случае, и вы не можете создать экземпляр шаблона без его параметризации.
Вот рабочий пример вашего кода со специализацией Bar.
#include <iostream>
using namespace std;
template <typename T = int>
struct Foo {
T t;
Foo() { cout << "Foo" << endl; }
};
template <typename T>
struct Baz {
T t;
Baz() { cout << "Baz" << endl; }
};
template <typename T>
struct Bar {
T t;
Bar() { cout << "Bar" << endl; }
};
template <template <typename > class T,class Y>
struct Bar<T<Y>>
{
T<Y> data;
Bar() : data() { cout << "Bar Specialization" << endl; }
};
int main()
{
Bar<Foo<>> a; //matches the specialization with T = template<typename> Foo and Y=int
Bar<Baz<float>> b; //matches the specialization with T = template<typename> Baz and Y=float
Bar<int> c; //matches the primary template with T=int
return 0;
}
Demo