2013-07-10 2 views
4

Это вопрос из любопытства по правилам 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, или если это хорошо определенное использование шаблонов.

Было бы интересно увидеть практические примеры этого.

+4

Нет неопределенного поведения. Он работает так, как ожидалось. Создание экземпляра шаблона может быть получено из другого экземпляра шаблона (помните, что два отдельных экземпляра одного шаблона являются двумя отдельными классами). Например, это позволяет вам иметь 'A ', который имеет функцию 'bar()' тогда и только тогда, когда 'X! = 0'. –

ответ

3

Это стандартная техника, которая довольно часто используется при рекурсивном определении 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 уровней рекурсивного наследования.

0

Это относится к C++. Шаблон класса A<1> является совершенно другим животным из другого класса шаблона A<0>.

Фактически, то, что вы построили здесь, похоже на то, что называется Curiously Recurring Template Pattern.