Cas*_*sey 30 c++ templates pointers reference template-specialization
摘要
有没有办法在模板化类型上调用类方法,该模板可能是指针或引用而不知道哪个而不是获取编译器/链接器错误?
细节
我有一个模板化的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
Run Code Online (Sandbox Code Playgroud)
但它们可能是指针或引用,因为它们都是从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
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是当间接(或缺少)未知时调用类方法的能力,并且由于模板,生成了两组代码:
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;
//...
}
Run Code Online (Sandbox Code Playgroud)
如果我改变上面的行来使用.(点)表示法:
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;
//...
}
Run Code Online (Sandbox Code Playgroud)
如果我删除基于引用的类型,而不是基于指针的类型(包括在Quadtree类的声明和用法中),我得到了错误left of .<function-name> must have class/struct/union.
如果我删除基于指针的类型以支持基于引用的类型(包括在Quadtree类的声明和用法中),我reference to pointer is illegal再次得到上述内容.
编译器:VS2010-SP1
Naw*_*waz 43
可以使用小的重载函数将引用转换为指针:
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!
Run Code Online (Sandbox Code Playgroud)
而不是这样做:
if(elem->Intersects(_bounds) == false) return false;
if(elem.Intersects(_bounds) == false) return false;
Run Code Online (Sandbox Code Playgroud)
做这个:
if( ptr(elem)->Intersects(_bounds) == false) return false;
Run Code Online (Sandbox Code Playgroud)
如果elem是参考,ptr则将选择第一个过载,否则将选择第二个过载.两者都返回指针,这意味着无论elem代码中的内容如何,表达式ptr(elem)将始终是一个指针,您可以使用它来调用成员函数,如上所示.
因为ptr(elem)是指针,这意味着检查它NULL是个好主意:
if( ptr(elem) && (ptr(elem)->Intersects(_bounds) == false)) return false;
Run Code Online (Sandbox Code Playgroud)
希望有所帮助.