2016-12-29 2 views
1

Рассмотрим приведенное ниже определение класса с глубоко вложенными частными данными.Публичные итераторы C++/STL для глубоко вложенных личных данных

template <typename T, typename U, typename V> 
class NestedData { 
private: 
    typedef std::vector<V> L3; 
    typedef std::map<U, L3> L2; 
    typedef std::map<T, L2> L1; 
    L1 inner_data; 
}; 

Предположим, мы хотим добавить открытый интерфейс для повторения каждого из трех уровней. То есть, мы хотим, чтобы позволить клиенту построить три вложенных циклов, которые перебирать каждое значение типа V, зная связанные значения типов U и T. Можно добавить следующие методы:

L1::const_iterator begin() const { return inner_data.begin(); } 
L1::const_iterator end() const { return inner_data.end(); } 

В этом случае , результаты от итератора были бы парами, причем правая сторона ссылалась на тип L2. Хотя ссылка const, она предоставляет полный API типа std :: map, что нежелательно для открытого интерфейса. Чистое решение предложит только обертку, позволяющую перебирать L2. Тем не менее, я не видел никаких стандартных идиом для такого рода инкапсуляции контейнеров STL, и даже в лучшем случае реализация решения, похоже, создает высокую степень раздувания кода.

Что было бы общим решением этой проблемы, которая хорошо сочетается с общими соглашениями на C++?

+0

Мне интересно, возможно, вы захотите пересмотреть свою структуру данных, чтобы сделать их немного менее «вложенными» ... –

ответ

2

Просто выставите карту через const геттер. Выявление итератора по-прежнему привязывает ваших пользователей к базовому типу данных, но это приводит к их повреждению - например, они не могут использовать find, поэтому есть недостаток без какой-либо выгоды.

Если вы можете переделать свой класс таким образом, чтобы внутренняя карта полностью стала детализацией реализации, и клиенты никогда не захотели ее увидеть - чем вы удалите итераторы и сеттеры, а затем вы увидите некоторые значимые функции.

+0

+1 - Также, разоблачая карту через const ref, если ваши клиенты используя авто правильно, когда они повторяются, даже если ваша структура данных изменяет их код, не нужно. – RyanP

+0

Предоставление всего API «карты», или даже детали, что есть «карта», не воспринимается для интерфейса. Я ищу способы добиться адекватной инкапсуляции. – epl

+0

Открывая итератор карты, вы подвергаете отображение самой карты. Разве вы не видите? – SergeyA

0

Я бы создал пользовательский итератор, который обеспечивал бы значения T, U, V при повторении. Это полностью изолирует пользователя от деталей реализации ваших данных. Если вам действительно нужна логика вложенного типа. Тогда я бы использовал пользовательский итератор, который вернул объект-адаптер, который вернет конечный итератор в список.