概要
コンパイラー/リンカーエラーを取得せずに、ポインターまたは参照であるテンプレート化された型でクラスメソッドを呼び出す方法はありますか?
詳細
次の重要なユーザー定義型のいずれかを取ることができるテンプレート化された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
しかし、これらはポインタである可能性がありますOR参照はすべて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
小さなオーバーロードされた関数を使用してreferenceをpointerに変換できます。
_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)
は常にpointerになります。上記のように、を使用してメンバー関数を呼び出すことができます。
ptr(elem)
はポインターであるため、NULL
をチェックすることをお勧めします。
_ if( ptr(elem) && (ptr(elem)->Intersects(_bounds) == false)) return false;
_
お役に立てば幸いです。