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.