Проблема с шаблонами в том, что для любого
template <typename T>
class C { };
любые две пары C<TypeA>
и C<TypeB>
являются абсолютно не связанными классами & ndash; это даже в том случае, если TypeA
и TypeB
отличаются только по const
-ness.
Так что то, что вы на самом деле хотите получить, технически невозможно. Я не буду сейчас представлять новый обходной путь, поскольку уже есть , но попробуйте посмотреть немного дальше: Как уже отмечалось в комментариях, вы могли бы столкнуться с проблемой XY.
Вопрос: что бы пользователь делал с таким списком? Возможно, он / она перебирает это - ndash; или получить доступ к отдельным элементам. Тогда почему бы не сделать так, чтобы весь ваш класс выглядел / вел себя как список?
class typeA
{
// wondering pretty much why you need a shared pointer here at all!
// (instead of directly aggregating the list)
shared_ptr<list<shared_ptr<typeB>>> l;
public:
shared_ptr<list<shared_ptr<typeB>>>::const_iterator begin() { return l->begin(); }
shared_ptr<list<shared_ptr<typeB>>>::const_iterator end() { return l->end(); }
};
Если бы вы использовали вектор вместо списка, я бы все же предоставил оператор индекса:
shared_ptr<typeB /* const or not? */> operator[](size_t index);
Теперь одна проблема все еще остается нерешенной: два возвращенных const_iterators
имеют неизменный общий указатель, но pointee все еще изменчив!
Это небольшая проблема - вам нужно сейчас реализовать свой собственный класс итератора:
class TypeA
{
public:
class iterator
{
std::list<std::shared_ptr<int>>::iterator i;
public:
// implementation as needed: operators, type traits, etc.
};
};
Посмотрите на std::iterator
для полного примера & ndash; Имейте в виду, однако, что std::iterator
устарела, поэтому вам нужно самостоятельно реализовать свойства типа.
Используемый тег итератора будет std::bidirectional_iterator_tag
или random_access_iterator_tag
(contiguous_iterator_tag
с C ++ 20), если вы используете std::vector
внутри.
Теперь важно, как вы реализуете два из необходимых операторов:
std::shared_ptr<int const> TypeA::iterator::operator*()
{
return std::shared_ptr<int const>(*i);
}
std::shared_ptr<int const> TypeA::iterator::operator->()
{
return *this;
}
Другие операторы просто передадут операцию внутренним итераторам (увеличение, уменьшение, если доступно, сравнение и т. Д.).
Я не утверждаю, что это Святой Грааль, путь, которым вы должны следовать при любых обстоятельствах. Но это ценная альтернатива, которую стоит хотя бы рассмотреть ...