2015-12-22 21 views
5

EDIT: In realtà non ho avuto la possibilità di testare nessuna delle soluzioni suggerite mentre andavo in vacanza, e quando sono tornato, le persone responsabile del modello di classe ha apportato alcune modifiche che mi hanno permesso di aggirare la necessità di utilizzare i tipi definiti nel modello di classe stesso.Utilizzo di tipi interni di un modello di classe da una classe specializzata

Grazie a tutti per il loro aiuto.


In poche parole - e non esitate a correggere il mio testo, i modelli sono ancora un po 'di voodoo per me, - ho bisogno di sapere se posso usare una (protected) struct o un #typedef definita all'interno di una classe modello dalla mia classe specializzata. Per esempio:

Questo è il modello di classe:

template<typename T> 
class A : public C<T> 
{ 
protected: 
    struct a_struct { /* Class template implementation, doesn't depend on T */ }; 
    void foo(a_struct a); 
}; 

che ho bisogno di specializzarsi completamente per T = VAL:

template<> 
class A<VAL> : public C<VAL> 
{ 
    void foo(a_struct a) 
    { 
     // My implementation of foo, different from the class template's 
    } 
}; 

Se faccio qualcosa di simile a questo, tuttavia, il compilatore si lamenta che a_struct è indefinito nella mia classe specializzata. Ho provato a specializzarmi e ad ereditare dal modello di classe, ma è diventato ... disordinato.

Ho visto alcune soluzioni, ma tutte hanno riguardato la modifica del modello di classe, che è qualcosa che non sono in grado di fare facilmente (team diverso).

Pensieri?

+0

Guarda una delle tante altre domande su SO in cui è spiegata la necessità di 'typename' nei template: http://stackoverflow.com/questions/610245/where-and-why-do-i-have-to -put-the-template-and-typename-keywords – JSF

+0

Scusa, ho inizialmente frainteso la tua domanda. Non vuoi ereditare un tipo dalla classe base ma piuttosto dalla versione non personalizzata di te stesso. – JSF

+0

Penso che tu possa creare una base falsa senza "modificare" l'originale. Crea una classe ereditandoti dall'originale e amicando la base falsa, in modo che la base falsa possa rubare la definizione del tipo dall'area protetta dell'originale nella propria area protetta. Quindi usa quella base falsa come vera base della specializzazione. – JSF

risposta

1

Non è bello, ma si può fare in questo modo:

template<typename T> 
class C 
{ 

}; 

template<typename T> 
class A : public C<T> 
{ 
protected: 
    friend A<int>; 
    // ^^^^^^ 
    struct a_struct { /* Class template implementation, doesn't depend on T */ }; 
    void foo(a_struct a); 
}; 

template<> 
class A<int> : public C<int> 
{ 
    using a_struct = typename A<void>::a_struct; 
    // ^^^^^^ 
    void foo(a_struct a) 
    { 
     // My implementation of foo, different from the class template's 
    } 
}; 
4

No, non è possibile utilizzare i membri della dichiarazione modello primario nella tua specializzazione del modello di classe. Questo perché in sostanza una specializzazione di classe template dichiara un template di classe completamente nuovo che viene applicato quando gli argomenti del template corrispondono alla specializzazione.

avete due opzioni disponibili, però, se si vuole fare qualcosa di simile nel tuo esempio:

  • È possibile specializzarsi il membro della classe template funzione. Questo è utile se è effettivamente solo una funzione membro che è speciale (o almeno il numero delle funzioni membro è limitato).
  • È possibile portare la dichiarazione del membro (tipo) in una classe di base comune.

Poiché in una modifica è stato indicato che non è possibile modificare il modello di classe stesso, la specializzazione della funzione membro sembra l'opzione migliore.

Una semplificato example di specializzarsi una funzione membro solo

template< class T> 
class Printer 
{ 
public: 
    struct Guard {}; 
    void DoPrint(const T& val) 
    { 
     Guard g; 
     (void)g; 
     std::cout << val << '\n'; 
    } 
}; 

struct Duck {}; 

template<> 
void Printer<Duck>::DoPrint(const Duck& val) 
{ 
    Guard g; 
    (void)g; 
    std::cout << "Some duck\n"; 
} 

Il Guard qui viene utilizzato solo per dimostrare che questo tipo è disponibile sia al primario e l'attuazione specializzato di DoPrint().

0

o come circa, riaffermando struct a_struct nel modello specializzato, con la stessa funzionalità di quello predefinito.

So che potrebbe non suonare bene poiché è necessario iniettare in tutti i modelli specializzati. Ma questo è quello a cui posso pensare ora.