Наследование шаблонных классов другой специализации
Это вопрос из любопытства о правилах C++ без какого-либо реального практического использования. Работая с шаблонами, я создал иерархию классов следующим образом:
#include <stdio.h>
// Declaration
template <int X = 0>
struct A;
// Specialization for X = 0
template <>
struct A<0>
{
virtual void foo()
{
printf("A<0>::foo()\n");
}
};
// Extended generalized implementation
template <int X>
struct A : public A<0>
{
virtual void foo()
{
printf("A<1>::foo()\n");
}
virtual void bar()
{
printf("A<1>::bar()\n");
}
};
int main()
{
A<> a0;
A<1> a1;
a0.foo();
a1.foo();
a1.bar();
return 0;
}
Этот код прекрасно скомпилирован в Visual Studio и выдает ожидаемый результат:
A<0>::foo()
A<1>::foo()
A<1>::bar()
Это допустимая практика проектирования C++? Это, конечно, выглядит странно для меня, поэтому мне интересно, если это какое-то неопределенное поведение, которое просто работает в зависимости от компилятора с большим количеством подводных камней и ошибок, или это четко определенное использование шаблонов.
Было бы интересно увидеть любые практические примеры этого.
2 ответа
Это стандартная методика, которая довольно часто используется при определении template
рекурсивно.
Примером такой техники могут быть последовательности целых чисел:
template<int...s> struct seq {typedef seq<s...> type;};
В частности, в их поколении:
template<int max, int... s> struct make_seq:make_seq<max-1, max-1, s...> {};
template<int... s> struct make_seq<0, s...>:seq<s...> {};
который описывается рекурсивно и просто путем наследования от другого экземпляра template
,
Чтобы быть явным, make_seq<7>::type
является seq<0,1,2,3,4,5,6>
через 7 уровней рекурсивного наследования.
Это действительно в отношении C++. Шаблон класса A<1>
это совершенно другое животное из другого шаблона класса A<0>
,
Фактически, то, что вы создали здесь, похоже на то, что называется Curly Recurring Template Pattern.