Настройки
Если вы хотите, чтобы итераторы возились с тем, что они повторяют, прежде чем вернуть это, boost::transform_iterator
довольно хороши. Вы передаете им унарную функцию, которая преобразует результат базового итератора operator*()
, а преобразующий итератор затем возвращает это:
template<typename Map>
struct iterator_transform_traits_map_second {
typedef typename Map::value_type value_type;
typedef typename Map::mapped_type result_type;
result_type& operator()( value_type& v) const {return v.second;}
const result_type& operator()(const value_type& v) const {return v.second;}
};
typedef
boost::transform_iterator<iterator_transform_traits_map_second>
transformed_iterator;
Все идет нормально. Но.
К чему это приводит
Вашим коллегам нравится этот блестящий новый инструмент, и они тоже начинают его использовать, и довольно скоро кто-то собирает в заголовке то, что вы уже придумали. Вот наш:
iterator_transform_traits_map_first
iterator_transform_traits_map_second
iterator_transform_traits_map_deref
(разыменовывает любую запись контейнера)iterator_transform_traits_map_deref_second
(разыменовывает запись картыsecond
)iterator_transform_traits_map_dynamic_cast
(выполняетdynamic_cast<>()
запись любого контейнера)iterator_transform_traits_map_any_second
(выполняетany_cast<>()
над записью картыsecond
)
Конечно, при этом упускается множество полезных (потому что они еще никому не нужны) и совсем не масштабируется. эм>. Мне только что было поручено написать итератор, который разыменовывает second
записи карты и выполняет dynamic_cast<>()
, и я отказался просто добавить iterator_transform_traits_map_dynamic_cast_deref_second
и двигаться дальше.
Что я хочу
Вместо этого я пытаюсь написать несколько базовых трейтов и трейты, формирующие время компиляции, которые позволяют назвать пару из них в качестве параметров шаблона и просто конвейеризируют вызовы. В идеале я хочу что-то вроде этого:
typedef
boost::transform_iterator<
iterator_transform_traits< iter_transf_tr_second
, iter_transf_tr_deref
, iter_transf_tr_dynamic_cast<derived>
>
>
transformed_iterator;
Моя текущая идея состоит в том, чтобы рекурсивно получить шаблон оболочки и заставить его рекурсивно вызывать все черты, передавая вывод от одного к другому. Я сделал что-то подобное десять лет назад и имею общее представление о том, как это сделать. Однако в последний раз я делал это пешком. То есть всю метамагию шаблона я реализовал сам.
Глупо, конечно, учитывая, что теперь у нас есть boost.mpl, boost.fusion и т. д., поэтому я бы предпочел использовать то, что уже есть. Однако после того, как я повозился с этим днем, стало ясно, что мне нужно многому научиться, прежде чем я это сделаю. И хотя я не против узнать все это, у меня есть кое-кто, кто дышит мне в затылок, которому нравится то, что я делаю, но он говорит, что ему все равно придется махнуть рукой, потому что есть этот крайний срок... Теперь у меня есть выбор: просто напишите чертову iterator_transform_traits_map_dynamic_cast_deref_second
, скопируйте много кода, который гнил десять лет и строился на нем, или придумайте чистое решение.
Вот где вы входите.
Вопрос
Как бы вы реализовали составные характеристики, используя уже существующие?
Платформа
Однако есть одна проблема: мы используем встроенную платформу и застряли на GCC 4.1.2, что означает C++03, TR1 и буст 1,52. Никаких переменных аргументов шаблона, никаких decltype
и всех этих причудливых вещей.
tr_second<tr_deref<tr_dynamic_cast<Derived, tr_identity>>>
. - person Puppy   schedule 30.01.2014