C ++模板专门化,可以明确地调用可能是指针或引用的类型的方法

时间:2013-01-22 19:35:46

标签: 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

但它们可能是指针或引用,因为它们都是从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

1 个答案:

答案 0 :(得分:41)

可以使用小重载函数将引用转换为指针

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,否则将选择第二个重载elem。两者都返回指针,这意味着无论代码中ptr(elem)是什么,表达式ptr(elem)将始终是指针,您可以使用它调用成员函数,如上所示。

由于NULL是指针,这意味着检查它 if( ptr(elem) && (ptr(elem)->Intersects(_bounds) == false)) return false; 是个好主意:

{{1}}

希望有所帮助。