32

概要

ポインターまたは参照である可能性があるテンプレート化された型でクラス メソッドを呼び出す方法はありますか?


詳細

次の重要なユーザー定義型のいずれかを取ることができるテンプレート化された QuadTree 実装があります。

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

しかし、それらはすべて a2de::Shape から派生しているため、ポインターまたは参照である可能性があります。したがって、特殊化は次のように宣言されます。

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

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

私が抱えている問題は、間接化 (またはその欠如) が不明なときにクラスメソッドを呼び出す機能であり、テンプレートのために両方のコードセットが生成されます。

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;

    //...
}

を使用するように上記の行を変更すると、. (ドット)表記:

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;

    //...

}

ポインターベースの型を優先して参照ベースの型を削除すると (Quadtree クラスの宣言と使用を含む)、エラーが発生しますleft of .<function-name> must have class/struct/union

参照ベースの型 (Quadtree クラスの宣言と使用を含む) を優先してポインタ ベースの型を削除すると、前述の状態reference to pointer is illegalが再び発生します。

コンパイラ: VS2010-SP1

4

1 に答える 1

50

小さなオーバーロードされた関数を使用して、参照ポインターに変換できます。

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!

これを行う代わりに:

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

これを行う:

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

が参照の場合elem、最初のオーバーロードptrが選択され、それ以外の場合は 2 番目が選択されます。どちらもpointerを返します。つまりelem、コードの内容に関係なく、上記のように、式ptr(elem)は常にメンバー関数を呼び出すために使用できるポインターになります。

ポインタなのでptr(elem)、それをチェックすることをnullptrお勧めします:

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

それが役立つことを願っています。

于 2013-01-22T19:42:03.540 に答える