Как избежать константы реализации дублирования кода и итераторов неконстанты?

Я реализую пользовательский контейнер с подобным STL интерфейсом. Я должен обеспечить регулярный итератор и итератор константы. Большая часть кода для двух версий итераторов идентична. Как я могу избежать этого дублирования?

Например, мой контейнерный класс Foo, и я - implementating FooIterator и FooConstIterator. Оба из итераторов должны предоставить методы как operator++() которые идентичны.

Мой вопрос подобен тому, Как я удаляю дублирование кода между подобной константой и функциями членства неконстанты?, но ответ, к которому характерен для константы и методов неконстанты, особенно средства доступа. Я не вижу, как это могло бы сделать вывод к проблеме итератора.

Если я имею FooIterator произойдите из FooConstIterator и расширьте его с помощью дополнительных методов неконстанты? То, что или приводит к виртуальным методам или сокрытию метода, которые кажутся несоответствующими здесь.

Возможно, FooIterator должен содержать a FooConstIterator. Хотя тот подход действительно уменьшает дублирование реализации, это, кажется, повторно вводит много шаблонных определений метода.

Есть ли умный шаблонный метод для генерации этих двух итераторов из единственного определения? Или возможно существует путь к - дрожь - использует препроцессор для искоренения этих почти идентичных классов.

Я попытался смотреть на свою локальную реализацию STL, чтобы видеть, как она обрабатывает это. Существует столько классов помощника, что у меня есть понимание проблемы дизайн, но похоже, что функциональность просто дублирована.

В предыдущих проектах мой пользовательский контейнер был создан сверху стандартного контейнера STL, таким образом, я не должен был обеспечивать свои собственные итераторы. Это не опция в этом случае.

52
задан Community 23 May 2017 в 02:34
поделиться

2 ответа

Вы можете использовать CRPP и общую базу для «ввода» методах (но вы все еще должны дублировать CTOR в текущем C ++) или просто используйте препроцессор (не требуется не требуется, не требуется, обрабатывает CTORS):

struct Container {

#define G(This) \
This operator++(int) { This copy (*this); ++*this; return copy; }
// example of postfix++ delegating to ++prefix

  struct iterator : std::iterator<...> {
    iterator& operator++();
    G(iterator)
  };
  struct const_iterator : std::iterator<...> {
    const_iterator& operator++();
    G(const_iterator)
  };

#undef G
// G is "nicely" scoped and treated as an implementation detail
};

Использовать STD: : ITERATOR, TYPEDEFS Это дает вам, и любые другие Typectefs, которые вы можете сделать, чтобы сделать макрос прямо вперед.

1
ответ дан 7 November 2019 в 09:36
поделиться

Очевидно, что выполняется сборка по адресу 0080h. Это не может быть правильным, так как диапазон адресов 0000h--3FFFh заблокирован на странице ROM 0. Действительно, согласно этому примеру, вы собираете до 4000h. Таким образом, ваша проблема заключается в том, что ваш CALL входит в встроенное ПО, а не в приложение.

-121--4746403-

По многим причинам, если не требуется сделать что-то необычное, следует прикреплять сообщения об ошибках к определенным полям (проще выполнить единичные тесты, проще изменить ошибки позже, вы можете отображать маркеры рядом с недопустимыми полями, если хотите, и т.д.). Я думаю, что то, что вы хотите сделать, может быть достигнуто с помощью:

class Product < ActiveRecord::Base
  validates_numericality_of :name, :if => lambda{ |obj| obj.prod_price? }
  validates_presence_of :name
end
-121--3348396-

В дополнение к предложению, что вы можете шаблонизировать константу и не константу, вы можете также уменьшить объем работы, взглянув на Boost.Iterator учебник - который также упоминает то же самое.

2
ответ дан 7 November 2019 в 09:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: