2011-12-10 16 views
5

Che cosa posso fare per fare questo lavoro:autoreferenziale Template in argomento di un template

template<class C, class V, Test V::*> 
class Test { 
}; 

mi dà errore di compilazione:

unknown type name 'Test' 

Si tratta di un modello autoreferenziale, per ora, che doesn sembra possibile Cosa potrebbe essere fatto per farlo funzionare?

EDIT:

Ecco quello che avevo bisogno di questo per. Voglio implementare uno schema di relazione bidirezionale (pensa genitore-figlio) con il minimo sforzo di codifica.

template <class O, class T, Reference<T, O, Reference O::*> T::* opposite> 
class Reference 
{ 
    T **data; 
    int count; 
public: 
    Reference(): data(new T*[N]), count(0) {} 
    ~Reference() {delete[] data;} 
    Reference &add(T *t) { 
     handleOtherSide(); 
     return link(t); 
    } 
    // a lot of stuff to implement this 
}; 

Questa è la classe di raccolta. Ecco come sarebbe essere utilizzato:

class Partner 
{ 
public: 
    Reference<Partner, Address, &Address::partner> addresses; 
}; 

class Address 
{ 
public: 
    Reference<Address, Partner, &Partner::addresses> partner; 
}; 

Il mio obiettivo è quello di avere tutto il necessario per riferimento al lavoro essere fornito come argomento di un template, in modo che non v'è alcuna necessità di fornire costruttori di classi come Partner e Indirizzo (attualmente fornisco il puntatore membro opposto come argomento costruttore, ma ciò richiede che io abbia costruttori espliciti per le classi partecipanti). Avrei anche bisogno di passare o calcolare un puntatore "proprietario" alla classe Reference. Ho lasciato questo problema qui perché voglio concentrarmi sull'aspetto del modello autoreferenziale.

Il modo più semplice per pensarci è boost :: bimap. Ma il problema con bimap è che non voglio il bimap che racchiude, ma solo la parte sinistra e destra di esso. anche il bimap non è fattibile perché porterebbe a un singolo bimap che gestisce tutte le associazioni di una relazione specifica. Potrebbe contenere un gran numero di oggetti che rallentano le operazioni su di esso.

+2

A cosa serve? Probabilmente è molto più semplice implementarlo in modo diverso dall'autoreferenziazione. – Jon

+5

Ho dovuto forzare questa domanda per togliere l'OP dal suo conteggio della reputazione 666. –

+2

Qual è l'obiettivo che stai cercando di ottenere con un modello ricorsivo, se non ti dispiace chiederlo? – dasblinkenlight

risposta

1

Il problema è, che cosa voglio ottenere non è possibile in C++, almeno non con i modelli e la quantità di codice e le classi sto puntando a (leggi: singola linea di codice per socio). Inizia con il compilatore che richiede dichiarazioni in avanti e tipi completamente definiti, il che rende i membri di valore parziale e gli argomenti del modello di tale impossibile (in caso di dipendenze cicliche). Quindi non è possibile avere un puntatore membro come argomento modello quando la classe di quel membro non è ancora del tutto definita. La causa principale di tutto questo è come funziona il compilatore: è single pass. E non c'è nulla che io possa fare al riguardo.

La soluzione consiste nell'utilizzare membri di riferimento o una classe di base in stile OO o un boost :: qualsiasi contenitore di stile per evitare i modelli. Con quest'ultimo 2 potrebbe essere possibile avere membri con valore.

2

Stai cercando qualcosa di simile? E 'modello non autoreferenziale, ma è possibile specificare classe derivata da un tipo di modello per la classe base e classe di base può chiamare metodi derivati ​​ecc .:

template< typename PType, typename PDerived > 
class TBase 
{ 
    //do stuff with TDerived 
public: 
    bool foo(void) 
    { 
    return (static_cast< PDerived* > (this)->bar()); 
    } 
}; 

template< typename PType > 
class TDerived : public TBase< PType, TDerived<PType> > 
{ 
    friend class TBase< PType, TDerived<PType> > ; 
    //do stuff 
protected: 
    bool bar(void) 
    { 
    return (true); 
    } 
}; 

EDIT: Ancora una volta, io non sono sicuro di quello che è il tuo finale obbiettivo. Ecco una soluzione a ciò che penso tu voglia, o, almeno, qualche suggerimento su cosa potresti usare per implementare il tuo design. L'unico requisito che ho inserito è che sia sia TPartner abbiano la stessa funzione. Vedi se è quello di cui hai bisogno. In linea di principio, puoi creare una classe helper e utilizzare CRTP per accedere alla funzione membro tramite un puntatore, ma non penso che tu ne abbia realmente bisogno.

template< typename PType1, typename PType2 > 
class TReference 
{ 
public: 
    int mFlag; 

    TReference() : 
    mFlag(0) 
    { 
    } 
    TReference(int fFlag) : 
    mFlag(fFlag) 
    { 
    std::cout << "Creating reference " << PType1::sName << " -> " << PType2::sName << "." << std::endl; 
    } 
    TReference< PType2, PType1 > AccessOpposite(void) 
    { 
    PType2 lTmp; 
    lTmp.Opposite(); 

    return TReference< PType2, PType1 > (-1); 
    } 
}; 

class TPartner; 

class TAddress 
{ 
public: 
    static const char* sName; 
    TReference< TAddress, TPartner > mRef; 

    void Opposite(void) 
    { 
    std::cout << sName << "::Opposite" << std::endl; 
    } 
}; 

class TPartner 
{ 
public: 
    static const char* sName; 
    TReference< TPartner, TAddress > mRef; 

    TReference< TAddress, TPartner > Opposite(void) 
    { 
    std::cout << sName << "::Opposite" << std::endl; 
    } 
}; 

const char* TAddress::sName = "TAddress"; 
const char* TPartner::sName = "TPartner"; 

int main(void) 
{ 
TAddress lAddress; 
TPartner lPartner; 

std::cout << lAddress.mRef.mFlag << " " << lPartner.mRef.mFlag << std::endl; 

lPartner.mRef = lAddress.mRef.AccessOpposite(); 

std::cout << lAddress.mRef.mFlag << " " << lPartner.mRef.mFlag << std::endl; 

return (0); 
} 
+0

Sembra molto interessante e divertente. Va bene non dichiarare la barra membro() a livello di classe base? –

+0

Sì, è ok a causa del modo in cui le funzioni del modello vengono istanziate. 'pippo' non verrà istanziato fino a quando non viene effettivamente chiamato nel codice e a quel punto' TDerived' è già definito. Cerca CRTP per ottenere maggiori informazioni. – lapk

+0

Dopo aver guardato questo per alcuni giorni devo dire come questo possa risolvere il mio problema è oltre me. Forse puoi adottare il mio esempio un po 'di più in modo che io possa vedere la soluzione? –

Problemi correlati