Может быть целесообразно обеспечить преобразование из Points3DTopoList в PointsList, учитывая, что Point3DTopo является производным от Point. Наследование, которое обеспечивает автоматическое преобразование, возможно, но я подозреваю, что ваши требования к общедоступному интерфейсу (не включены в вопрос) делают его более сложным, чем актив.
Пример предоставления пути конвертации:
template<class T>
struct PointsList {
// Points3DTopoList needs a way to construct a PointsList
template<class Iter>
PointsList(Iter begin, Iter end)
: points(begin, end)
{}
private:
std::vector<Point<T> > points;
};
template<class T>
struct Points3DTopoList {
operator PointsList<T>() const {
return PointsList<T>(points.begin(), points.end());
}
PointsList<T> to_points_list() const {
return PointsList<T>(points.begin(), points.end());
}
private:
std::vector<Point3DTopo<T> > points;
};
Это обеспечивает два пути преобразования - обычно вы выбираете один, а другой не предоставляете. Оператор преобразования является неявным преобразованием (в C ++ 0x вы можете пометить его явным образом), в то время как названный метод не является «преобразованием» в технических терминах (таким образом, никогда не применяется для любого неявного или явного преобразования), но явно вызывается и использовал таким образом.
Вы также можете предоставить явное преобразование с помощью явного конструктора в PointsList, который принимает Points3DTopoList, и это работает в текущем C ++ за счет инвертирования отношения зависимости от того, как оно обычно лежит: то есть PointsList будет знать и заботиться о Points3DTopoList, а не наоборот.
Однако для вас может иметь смысл предоставить контейнер "generic-Point"; то есть тот, который принимает любой конкретный точечный тип.
template<class Point>
struct GenericPointContainer {
private:
std::vector<Point> points;
};
Самым большим преимуществом здесь является то, что методы GenericPointContainer могут использовать различные функции из производных классов Point, которые отсутствуют в самой Point, но все же могут быть созданы непосредственно в Point. Это работает, потому что все методы не создаются при создании экземпляра шаблона класса, и практический пример - то, как std :: reverse_iterator перегружает оператор + =, который работает только для итераторов с произвольным доступом, но может быть создан на итераторах без случайного доступа, такой как std :: reverse_iterator :: iterator>.
Тогда различные классы списка могут стать простыми определениями типов, даже если они все еще требуются:
typedef GenericPointContainer<Point<int> > PointsList;
typedef GenericPointContainer<Point3DTopoList<int> > Points3DTopoList;
C ++ 0x действительно помог бы вам с шаблонами typedefs (вы можете использовать перепривязку в текущем C ++, но это становится тупым); как вы можете видеть, я должен был указать T для typedefs, поэтому он не такой общий, как в противном случае.