Я полностью понимаю вопрос пользователя. Он / она хочет создать собственный класс-контейнер, который предоставляет пользователю STL-подобный интерфейс. Стандартных контейнеров STL не хватает каким-либо образом, и поэтому они не являются подходящим выбором.
Например, у меня есть класс интерфейса для «Dataline» с именем IDataline. Реализация интерфейса IDataLine берет при построении строку с разделителями, анализирует ее и предоставляет список полей. через const_iterator с семантикой forward_iterator_tag.
Ни один контейнер STL не может сделать это из коробки.
Кроме того, мой клиентский класс хочет иметь возможность перебирать два поля строки данных и сравнивать их, поле за полем.
Я определил интерфейс IDataline следующим образом:
1 class IDataline
2 {
3 public:
4 class const_iterator
5 {
6 public:
7 virtual const_iterator& operator=(const const_iterator& rhs) =0;
8 virtual bool operator==(const const_iterator& rhs) =0;
9 virtual bool operator!=(const const_iterator& rhs) =0;
10 virtual const_iterator& operator++() =0;
11 virtual const_iterator operator++(int) =0;
12 virtual const Field& operator*() =0;
13 virtual const Field* operator->() =0;
14 virtual const Field& operator[](size_t idx) =0;
15 virtual size_t offset() =0;
16 };
17
18 virtual const_iterator begin() =0;
19 virtual const_iterator end() = 0;
20 };
Проблема может быть замечена в строках 11, 18 и 19 - нам нужно иметь возможность вернуть const_iterator, для которого требуется конструктор копирования, но, поскольку он является виртуальным, нет ни конструктора по умолчанию, ни конструктора копирования (для тип интерфейса) и компилятор (правильно) балки.
Вы можете утверждать, что я мог бы определить begin () и end () как:
virtual const_iterator& begin() = 0;
virtual const_iterator& end() = 0;
Затем я могу создать два экземпляра специализированного итератора на специализированном хосте и вернуть ссылки (или указатели для тех, кто предпочитает их), чтобы заставить это работать для моего случая.
Проблема в том, что такая реализация не удовлетворяет всем требованиям для прямых итераторов и будет нарушаться в более общих случаях использования, которые основаны на семантике прямых итераторов.
Есть два способа, которые я нашел после небольшого раздумья (и коллеги проконсультировались), что это можно решить:
Должен ли ваш хост-класс быть полностью абстрактным? Если вы можете минимизировать абстракцию до того поведения, которое вам нужно изменить, то ваш инстанцируемый хост может встроить конкретный итератор (потому что экземпляр самого класса может быть создан), и у вас есть то, что вам нужно.
Эдуардо Леон выше указывает, что сам итератор может быть упакован с использованием идиомы pimpl (Указатель на реализацию). В то время как есть много материалов, которые подробно описывают эту технику, Basilev в комментариях ниже предложение Леона указывает на то, что он не верит, что идиома pimpl сработает. Мой коллега предложил мне попробовать методику, поэтому я разработаю проверенный образец. Если это сработает, я поделюсь этим. Если нет, я подробно опишу опыт, полученный в образце, и подожду, пока кто-нибудь более опытный, чтобы оценить, применима ли pimpl в этом случае.