Почему адрес элемента массива иногда принимают за объявление?

У меня есть несколько пользовательских итераторов, и время от времени я получаю странную ошибку, которую легко обойти, но я не понимаю, почему я ее получаю:

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 в последней строке компилируется?

Благодарю.

5

Решение

Прежде всего, мы можем сузить вашу проблему до следующих строк:

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};
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]