Specjalizacja szablonów C++, wywołanie metod na typach, które mogą być wskaźnikami lub odwołaniami jednoznacznie

Podsumowanie

Czy istnieje sposób na wywołanie metody klasy na typie szablonowym, która może być wskaźnikiem lub odniesieniem, nie wiedząc, które i nie uzyskać błędów kompilatora / linkera?


Szczegóły

Mam szablonową implementację QuadTree, która może przyjmować dowolny z następujących nietrywialnych typów zdefiniowanych przez użytkownika:

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

Ale mogą być wskaźnikiem lub odniesieniem, ponieważ wszystkie pochodzą z a2de:: Shape. Tak więc specjalizacje są deklarowane as:

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

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

Problemem, który mam, jest możliwość wywołania metody klasowej, gdy indirection (lub jej brak) jest nieznana i ze względu na szablony generowane są oba zestawy kodu:

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;

    //...
}

Jeśli zmienię powyższą linię, aby użyć . (kropka) zapis:

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;

    //...

}

Jeśli usunę typy oparte na referencjach na rzecz typów opartych na wskaźnikach (włączając w to deklarację i użycie klasy Quadtree), otrzymam błąd left of .<function-name> must have class/struct/union.

Jeśli usunę Typ oparty na wskaźniku w za typami bazującymi na referencjach (włączając w to deklarację i użycie klasy Quadtree) otrzymuję ponownie wspomniane reference to pointer is illegal.

Kompilator: VS2010-SP1

Author: Casey, 2013-01-22

1 answers

Małe przeciążone funkcje mogą być użyte do przekształcenia referencji w Wskaźnik :

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!

Teraz zamiast tego:

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

Zrób to:

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

Jeśli elem jest referencją, zostanie wybrane pierwsze przeciążenie ptr, w przeciwnym razie zostanie wybrane drugie. Oba zwroty pointer , co oznacza, że niezależnie od tego, co elem znajduje się w Twoim kodzie, wyrażenie ptr(elem) Zawsze będzie pointer, którego możesz użyć do wywołania funkcji Członkowskich, jak pokazano powyżej.

Ponieważ ptr(elem) jest wskaźnikiem, co oznacza sprawdzenie go pod kątem NULL bądź dobrym pomysłem:

 if( ptr(elem) && (ptr(elem)->Intersects(_bounds) == false)) return false;
Mam nadzieję, że to pomoże.
 39
Author: Nawaz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-22 19:56:18