У меня есть несколько пользовательских итераторов, и время от времени я получаю странную ошибку, которую легко обойти, но я не понимаю, почему я ее получаю:
uint8_t bytes[pitch*height];
array_iterator::col_iterator a( &bytes[0] );
array_iterator::row_iterator base_iter_begin(
array_iterator::col_iterator( &bytes[0] ), width, pitch );
array_iterator::row_iterator base_iter_end(
array_iterator::col_iterator( &bytes[pitch*height] ), width, pitch
);
У меня есть класс с именем array_iterator со встроенными typedefs row_iterator и col_iterator. Конструктор row_iterator принимает col_iterator в качестве первого аргумента. Первое и последнее утверждение работают просто отлично. Оператор middle не компилируется со следующей ошибкой:
test-2d-iterators.cc:780: error: declaration of 'bytes' as array of references
Пишу &(bytes [0]) не решает проблему (не удивительно, так как [] имеет более высокий приоритет, чем &). Конечно, я могу просто заменить «a» на явный вызов конструктора col_iterator, но зачем мне это? И если есть проблема, почему конструктор col_iterator в последней строке компилируется?
Благодарю.
Прежде всего, мы можем сузить вашу проблему до следующих строк:
struct row_iterator { ... };
typedef unsigned* col_iterator;
unsigned bytes[5];
row_iterator base_iter_begin(col_iterator(&bytes[0]));
И третья строка понимается как:
row_iterator base_iter_begin(col_iterator& bytes[0]);
И эта строка объявляет функцию, принимающую в качестве параметра массив из 0 ссылок на col_iterator и возвращающий int. Это действительно случай самый неприятный разбор как указано в комментариях.
Самый простой способ избавиться от этого — использовать инициализацию копирования вместо прямой инициализации (инициализация в C ++):
row_iterator base_iter_begin = row_iterator(col_iterator(&bytes[0]));
Который в вашем случае будет:
array_iterator::row_iterator base_iter_begin = array_iterator::row_iterator(array_iterator::col_iterator( &bytes[0] ), width, pitch );
НОТА: При условии, что вы используете C ++ 11, есть еще больше правил инициализации, и вы можете использовать инициализацию списка, чтобы избавиться как от шаблонного, так и от самого неприятного анализа:
array_iterator::row_iterator base_iter_begin{array_iterator::col_iterator(&bytes[0]), width, pitch};
Других решений пока нет …