sustantivo sinonimo significado recordar rae inequívoco inequivoco inequivocas inequivocamente ejemplo antonimo c++ templates pointers reference template-specialization

c++ - recordar - significado de inequivoco sinonimo



Especialización de plantilla C++, llamando a métodos en tipos que podrían ser punteros o referencias inequívocamente (1)

Resumen

¿Hay alguna manera de llamar a un método de clase en un tipo de plantilla que podría ser un puntero o una referencia sin saber cuál y no obtener errores de compilador / enlazador?

Detalles

Tengo una implementación de QuadTree con plantillas que puede tomar cualquiera de los siguientes tipos no triviales definidos por el usuario:

//Abstract Base Class a2de::Shape //Derived Classes a2de::Point a2de::Line a2de::Rectangle a2de::Circle a2de::Ellipse a2de::Triangle a2de::Arc a2de::Spline a2de::Sector a2de::Polygon

Pero podrían ser un puntero O una referencia, ya que todos se derivan de a2de :: Shape. Entonces las especializaciones se declaran como:

template class QuadTree<a2de::Shape&>; //...similar for all derived types as references. template class QuadTree<a2de::Shape*>; //...similar for all derived types as pointers

El problema que tengo es la capacidad de llamar a un método de clase cuando la indirección (o la falta de ella) es desconocida y debido a las plantillas, se generan ambos conjuntos de códigos:

template<typename T> bool QuadTree<T>::Add(T& elem) { //When elem of type T is expecting a pointer here //-> notation fails to compile where T is a reference i.e.: //template class QuadTree<a2de::Shape&> //with "pointer to reference is illegal" if(elem->Intersects(_bounds) == false) return false; //... }

Si cambio la línea anterior para usar el. (punto) notación:

template<typename T> bool QuadTree<T>::Add(T& elem) { //When elem of type T is expecting a reference here //. (dot) notation fails to compile where T is a pointer i.e.: //template class QuadTree<a2de::Shape*> //with "pointer to reference is illegal" if(elem.Intersects(_bounds) == false) return false; //... }

Si elimino los tipos basados ​​en referencias a favor de los tipos basados ​​en punteros (incluyendo en la declaración y uso de la clase Quadtree) obtengo el error left of .<function-name> must have class/struct/union .

Si elimino el tipo basado en puntero a favor de los tipos basados ​​en referencias (incluida la declaración y el uso de la clase Quadtree) obtengo que la reference to pointer is illegal antes mencionada reference to pointer is illegal nuevamente.

compilador: VS2010-SP1


Las pequeñas funciones sobrecargadas se pueden usar para convertir la referencia en puntero :

template<typename T> T * ptr(T & obj) { return &obj; } //turn reference into pointer! template<typename T> T * ptr(T * obj) { return obj; } //obj is already pointer, return it!

Ahora en lugar de hacer esto:

if(elem->Intersects(_bounds) == false) return false; if(elem.Intersects(_bounds) == false) return false;

Hacer esto:

if( ptr(elem)->Intersects(_bounds) == false) return false;

Si elem es una referencia, se seleccionará el primer ptr sobrecarga, de lo ptr se seleccionará el segundo. Ambos retornan el puntero , lo que significa que independientemente de qué elemento esté en su código, la expresión ptr(elem) siempre será un puntero que puede usar para invocar las funciones miembro, como se muestra arriba.

Como ptr(elem) es un puntero, lo que significa que debe verificarlo para NULL tenga una buena idea:

if( ptr(elem) && (ptr(elem)->Intersects(_bounds) == false)) return false;

Espero que ayude.