2012-06-20 14 views
5

Qualcuno conosce un metodo per utilizzare CRTP per contare il numero di sottoclassi di un oggetto?Come contare il numero di sottoclassi CRTP di una classe template?

Supponiamo di avere una configurazione simile a quella che segue:

template <typename T>  
class Object 
{ 
    .... 
}; 

const unsigned int ObjectSubClassCount = ...; 

class Subobject : public Object<SubObject> 
{ 
    .... 
}; 

class Second : public Object<Second> 
{ 
    .... 
}; 

e così via, in modo tale che, utilizzando TMP, potremmo avere una costante (ObjectSubClassCount) che rappresenta il numero totale di sottoclassi?

Qualcuno sa un modo per farlo?

Edit: Sono voler utilizzare il risultato come un parametro di template più tardi, quindi ho bisogno di essere fatto con TMP ...

+0

Giusto per notare, sto lavorando per risolvere questo problema, me stesso. Ti sto solo chiedendo ragazzi nel caso non lo faccia mai, o lo fai prima. – Serge

+0

Dovrebbe essere possibile - vuoi avere un contatore per le sottoclassi a ogni livello gerarchico o solo l'intero numero di sottoclassi di oggetti? – duselbaer

+0

Solo le sottoclassi di quel livello; Non mi aspetto un'erarchia. – Serge

risposta

2

senza l'obbligo di utilizzare il risultato come un parametro di template poi avrei provalo in questo modo:

// Class which increments a given counter at instanciation 
struct Increment { 
    Increment(std::size_t& counter) 
    { 
    counter++; 
    } 
}; 

// This is your template base 
template <typename T>  
class Object 
{ 
    private: 
    // For every instanciation of the template (which is done for a subclass) 
    // the class counter should get incremented 
    static Increment incrementCounter; 
}; 

// This is the global object counter 
static std::size_t classCounter; 

// Static Member Variable 
template<typename T> 
Object<T>::incrementCounter(classCounter); 

Non ho provato, ma dovrebbe fare. Per avere nuovamente il risultato disponibile come parametro template (MPL) non ho abbastanza esperienza in MPL, ma dubito che ciò sia possibile.

0

Ok, quindi mi sono imbattuto in una ... risposta un po 'accettabile. Ho pensato che non avrebbe funzionato se le sottoclassi non avessero assolutamente la conoscenza reciproca (voglio dire, stiamo parlando di programmazione piuttosto funzionale ...).

Ecco una soluzione per questo. Non è sicuramente la soluzione che vorrei; tuttavia, è un inizio. Ho forzato tutti gli oggetti a utilizzare un modulo di CRTP, ma uno che utilizza più di un formato di elenco collegato. In questo modo, i nostri sottoclassi devono provenire da un oggetto <> basati su modelli da:

A: si e B: il più recente sottoclasse definita in precedenza

ecco il mio codice per questo (io uso un modello da <type_traits> una volta, solo una nota)

template <typename T> //SFINAE check for the existance of subclasscount static member 
struct has_subclasscount 
{ 

    template <typename U> 
    static typename std::enable_if<sizeof(U::subclasscount) != 0, int>::type test(int); 

    template <typename U> 
    static char test(...); 

    static const bool result = (sizeof(test<T>(0)) == sizeof(int))?(true):(false); 
}; 


template <bool res, typename T> 
struct return_subclasscount //the value to return is 0 if false 
{ 
    static const int result = 0; 
}; 


template <typename T>  
struct return_subclasscount<true, T> //returns subclasscount only if the first parameter is true 
{ 
    static const int result = T::subclasscount; 
}; 


template <typename T>    //combines return_subclasscount and has_subclasscount 
struct get_subclasscount 
{ 
    static const int result = return_subclasscount<has_subclasscount<T>::result, T>::result; 
}; 


template <typename This, typename Prev> 
class Object 
{ 
public: 

    static const int subclasscount = 1 + get_subclasscount<Prev>::result; //the subclass count 
}; 


class sub1 : public Object<sub1, int> 
{ 

}; 


class sub2 : public Object<sub2, sub1> 
{ 

}; 


class sub3 : public Object<sub3, sub2> 
{ 

}; 

Queste ultime 3 classi vuote sono le sottoclassi che stiamo contando. Questo è il nostro file di intestazione. Nel nostro file cpp principale, abbiamo:

int main() { 

std::cout << sub3::subclasscount; 

char c; 
std::cin >> c; 
} 

L'esecuzione, otteniamo una semplice uscita di:

che conferma che ha funzionato. Ora, alcuni degli aspetti negativi di questa soluzione è:

  • Dobbiamo sapere quello che la nostra ultima sottoclasse definiti era, prima di aggiungere su.
  • Dobbiamo stare al passo con qualsiasi parte usiamo il contatore di sottoclasse, modificandolo sempre dall'ultima sottoclasse nell'elenco (questo può essere evitato usando una sottoclasse consistente "endoflist", che invece andrebbe mantenuta)

I lati positivi, tuttavia, includono il fatto che non è necessario mantenere alcuna delle sottoclassi precedentemente definite.Tuttavia, considero questa risposta più un "punto di partenza" che una "soluzione finale"; forse qualcosa che può essere ampliato?

(anche, questo può essere facilmente abusato per fare una forma di struttura ad albero, dove subclasscount sarebbe in realtà rappresentano la profondità di un dato nodo nell'albero)

Qualcuno ha qualche idea da qui?