2012-06-20 19 views
5

¿Alguien sabe de un método para usar CRTP para contar el número de subclases de un objeto?¿Cómo contar el número de subclases CRTP de una clase de plantilla?

supongamos que tenemos una configuración similar a la siguiente:

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

const unsigned int ObjectSubClassCount = ...; 

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

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

y así sucesivamente, de manera que, mediante TMP, podríamos tener una constante (ObjectSubClassCount) que representa el número total de subclases?

¿Alguien sabe una manera de hacer esto?

Editar: Estoy queriendo utilizar el resultado como un parámetro de plantilla más adelante, así que necesito que se haga con TMP ...

+0

Solo para observar, estoy trabajando para resolver este problema, yo mismo. Solo les pregunto chicos en caso de que nunca lo haga, o lo hacen primero. – Serge

+0

Debería ser posible - ¿desea tener un contador para las subclases en cada nivel de jerarquía o solo para el conjunto de subclases de objetos? – duselbaer

+0

Solo las subclases en ese nivel; No esperaba una jerarquía. – Serge

Respuesta

2

Sin el requisito de utilizar el resultado como un parámetro de plantilla más tarde lo haría pruébelo haciendo esto:

// 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); 

No lo he intentado pero debería hacer. Para tener el resultado disponible nuevamente como un parámetro de plantilla (MPL), no tengo suficiente experiencia en MPL pero dudo que esto sea posible.

0

Ok, así que me he encontrado con ... una respuesta algo aceptable. Pensé que no funcionaría si las subclases no tuvieran absolutamente ningún conocimiento mutuo (es decir, estamos hablando de algo de programación funcional ...).

Aquí hay una solución para esto. Definitivamente no es la solución que desearía; sin embargo, es un comienzo. He forzado a todos los objetos a utilizar una forma de CRTP, pero uno que utiliza más de un formato de lista vinculada. De esta manera, nuestros subclases deben derivarse de un objeto <> basados ​​en plantillas de:

A: sí y B: la más reciente subclase definida previamente

aquí es mi código para esto (yo uso una plantilla a partir de <type_traits> una vez, sólo 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> 
{ 

}; 

Estos últimos 3 clases vacías son las subclases que estamos contando. Este es nuestro archivo de encabezado. En nuestro archivo .cpp principal, tenemos:

int main() { 

std::cout << sub3::subclasscount; 

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

de ejecutarlo, obtenemos una salida simple:

lo que confirma que se ha trabajado. Ahora, algunos de los inconvenientes de esta solución es:

  • Debemos saber lo que era nuestra última subclase definida, antes de añadir sucesivamente.
  • Debemos mantenernos al día con cualquier lugar donde usemos el contador de subclase, siempre modificándolo desde la última subclase en la lista (esto puede evitarse utilizando una subclase "endoflist" consistente, que debería mantenerse en su lugar)

Las caras arriba, sin embargo, incluyen el hecho de que no necesitamos mantener ninguna de nuestras subclases previamente definidas.Sin embargo, considero esta respuesta más como un "punto de partida" que como una "solución final"; tal vez algo que se puede expandir?

(también, esto puede fácilmente ser objeto de abuso para hacer una forma de estructura de árbol, donde subclasscount sería en realidad representan la profundidad de cualquier nodo dado en el árbol)

Alguien tiene alguna idea de aquí?

Cuestiones relacionadas