В то время как работа над некоторой графикой кодирует некоторое время назад, я записал классы Rect и региона с помощью ints как базовый координатный держатель, и это хорошо работало. Регион был реализован как простое расширение класса списка STL и просто содержит список Rects.
Теперь мне также нужны те же виды использования классов, удваивается как базовый координатный держатель, и решенный, чтобы попробовать мои силы в templatizing это. Таким образом, я в основном заменил "интервал" "именем типа T" интеллектуальным способом и решил проблемы.
Но существует одна остающаяся проблема, которой озадачили меня. Я хочу вычислить ограничительную рамку региона путем выполнения объединения на всех Rect, которые включают его. Это хорошо работает если не templatized, но g ++ дроссели на итераторе списка, когда это - templatized.
Вот соответствующие нормы:
// 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 был определенным (например, интервал), "итератор, i" строк хорошо работают. Но в то, что Вы видите выше, g ++ на Ubuntu, испускает ошибки, которые я не нахожу очень информативными:
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;
но ничто, кажется, не работает.
Какие-либо предложения?
итератор
является зависимым типом (зависит от аргумента шаблона) и требует с префиксом typename
:
typename std::list< KRect<T> >::iterator i;
Лучшим стилем было бы предоставление typedef для всего класса:
template <typename T>
class KRegion : public std::list< KRect<T> >
{
typedef std::list< KRect<T> > base;
typedef typename base::iterator iterator;
// ...
};
I think gf has your answer, but I'd like to suggest having the region manage a list as a member instead of a base class:
template <typename T>
class KRegion
{
protected:
typedef std::list< KRect<T> > ListType;
ListType list;
public:
...
// Accessors
void addRect(KRect<T> & rect) { list->push_back(rect); }
...
KRect<T> boundingBox(void)
{
KRect<T> r;
ListType::iterator i;
for (i = list->begin(); i != list->end(); i++)
{
r.unionRect(*i);
}
return r;
}
...
};
My motivation for this suggestion is that you may, one day, want to use a different container for storing your KRects, and having the list as an internal member would let you do so without breaking all of your client code.