Часть исходного кода для проекта, над которым я работаю, который отвечает за сжатие последовательности 'событий', выглядит следующим образом:
#include <iterator>
#include <list>
typedef int Event;
typedef std::list<Event> EventList;
struct Compressor {
// Returns an iterator behind the last element which was 'eaten'
virtual EventList::const_iterator eatEvents( const EventList &l ) = 0;
};
// Plenty of Compressor subclasses exist
void compressAndCopyEatenEvents( Compressor &c ) {
EventList e;
e.push_back( 1 );
EventList::const_iterator newEnd = c.eatEvents( e );
EventList eatenEvents;
std::copy( e.begin(), newEnd, std::back_inserter( eatenEvents ) ); // barfs
}
Проблема здесь в том, что функция compressAndCopyEatenEvents
имеет неконстантный список событий; этот список передается методу eatEvents
, который принимает ссылку на const и возвращает const_iterator
. Теперь функция compressAndCopyEatenEvenst
хотела бы скопировать диапазон съеденных событий, поэтому она решает использовать некоторый алгоритм (std::copy
здесь, который, разумеется, можно также заменить на правильный вызов конструктора std::list
- точка является то, что эта проблема существует со всеми видами диапазонов).
К сожалению (?) Многие (если не все?) Диапазоны должны быть составлены из одного и того же типа итератора. Однако в приведенном выше коде e.begin () возвращает EventList::iterator
(поскольку объект не является константным), а newEnd является EventList::const_iterator
.
Есть ли здесь слабость дизайна, которая вызывает этот беспорядок? Как бы вы занялись этим?