Это вопрос из любопытства по правилам 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++? Мне это, конечно, кажется странным, поэтому мне интересно, если это какое-то неопределенное поведение, которое просто происходит в зависимости от компилятора с множеством ловушек и gotchas, или если это хорошо определенное использование шаблонов.
Было бы интересно увидеть практические примеры этого.
Нет неопределенного поведения. Он работает так, как ожидалось. Создание экземпляра шаблона может быть получено из другого экземпляра шаблона (помните, что два отдельных экземпляра одного шаблона являются двумя отдельными классами). Например, это позволяет вам иметь 'A', который имеет функцию 'bar()' тогда и только тогда, когда 'X! = 0'. –