【发布时间】:2010-02-08 01:34:03
【问题描述】:
不久前在处理一些图形代码时,我使用 int 作为底层坐标持有者编写了 Rect 和 Region 类,并且效果很好。 Region 是作为 STL 列表的简单类扩展实现的,并且只包含一个 Rect 列表。
现在我还需要使用双精度对象作为底层坐标持有者的相同类型的类,并决定尝试将其模板化。所以我基本上以智能的方式将“int”替换为“typename T”并修复了问题。
但还有一个问题让我很困惑。我想通过对包含它的所有 Rect 进行联合来计算区域的边界框。这在未模板化时工作正常,但当它被模板化时,g++ 会在列表迭代器上阻塞。
以下是相关代码:
// Rect class that always remains normalized
template <typename T>
class KRect
{
public:
// Ctors
KRect(void)
: _l(0), _t(0), _r(0), _b(0)
{
}
void unionRect(const KRect& r)
{
...
}
private:
T _l, _t, _r, _b;
};
// Region class - this is very brain-dead
template <typename T>
class KRegion : public std::list< KRect<T> >
{
public:
...
// Accessors
KRect<T> boundingBox(void)
{
KRect<T> r;
iterator i;
for (i = this->begin(); i != this->end(); i++)
{
r.unionRect(*i);
}
return r;
}
...
};
当该代码不是模板的一部分时,因此 T 是确定的(例如 int),“迭代器 i”行可以正常工作。但是在您上面看到的内容中,Ubuntu 上的 g++ 会发出错误,我认为这些错误信息并不多:
include/KGraphicsUtils.h: In member function ‘KRect<T> KRegion<T>::boundingBox()’:
include/KGraphicsUtils.h:196: error: expected ‘;’ before ‘i’
include/KGraphicsUtils.h:197: error: ‘i’ was not declared in this scope
include/KGraphicsUtils.h: In member function ‘KRect<T> KRegion<T>::boundingBox() [with T = int]’:
--- redacted ---:111: instantiated from here
include/KGraphicsUtils.h:196: error: dependent-name ‘std::foo::iterator’ is parsed as a non-type, but instantiation yields a type
include/KGraphicsUtils.h:196: note: say ‘typename std::foo::iterator’ if a type is meant
我的猜测是这是一个类型限定问题,带有一些我不熟悉的模板-y 旋转。我尝试了各种方法,例如:
std::list< KRect<T> >::iterator i;
this->iterator i;
但似乎没有任何效果。
有什么建议吗?
【问题讨论】:
-
您使用的是哪个编译器?我可以在 VC++2010 上编译它。
-
他已经说过 g++ - VC++ 传统上对于没有
typename或template的依赖名称非常宽松。 -
你永远不应该从 STL 容器继承,因为它们不被认为是多态的(即没有虚拟析构函数)。正确的方法是使用组合,并适当地编写转发方法......虽然它很乏味。
-
同意 - 但这是一个概念验证实现,必须快速编写,因此可以接受一些骇人听闻的快捷方式。
标签: c++ inheritance templates stl