2013-04-26 7 views
5

mam pewne zdefiniowane przez użytkownika iteratory, i co jakiś czas mam dziwny błąd, który jest łatwy do obejścia, ale nie rozumiem, dlaczego Dostaję go:Dlaczego adres elementu tablicy jest czasami mylony z deklaracją?

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 
); 

Mam klasy o nazwie array_iterator z osadzonymi typedefs row_iterator i col_iterator. Konstruktor row_iterator przyjmuje col_iterator jako swój pierwszy argument. Pierwsze i ostatnie oświadczenie działa dobrze. Bliski oświadczenie nie skompilować z powodu następującego błędu:

test-2d-iterators.cc:780: error: declaration of 'bytes' as array of references 

Pisanie & (bajty [0]) nie rozwiązuje problemu (co nie jest zaskoczeniem, ponieważ [] ma wyższy priorytet niż &). Oczywiście, mogę po prostu zastąpić "a" dla jawnego wywołania konstruktora col_iterator, ale dlaczego muszę? A jeśli jest jakiś problem, dlaczego konstruktor col_iterator w ostatniej linii kompiluje?

Dzięki.

+2

Większość Vexing Parse może? –

+1

Napisz * krótki * przykład, który usuwa problem. –

+0

To może być najbardziej szalona parse, ale nie jestem pewien. Czy trzecia linia nie parsowałaby w ten sam sposób? static_cast (& bytes [0]) rozwiązuje problem, ale samo dodanie parens wokół & bytes [0] nie powoduje. Przykro nam, że przykład nie jest bardziej destylowany, ale problem zdaje się przychodzić i odchodzić bez rymu lub przyczyny (tj. Jak trzecia linia różni się od drugiej?), Więc oparła się moim próbom. Z pewnością wygląda to na błąd parsowania, więc myślę, że nie zależy to od tego, czym właściwie jest row_iterator lub col_iterator. – user1806566

Odpowiedz

2

Przede wszystkim, możemy zawęzić problem do następujących linii:

struct row_iterator { ... }; 
typedef unsigned* col_iterator; 
unsigned bytes[5]; 
row_iterator base_iter_begin(col_iterator(&bytes[0])); 

I trzecia linia jest rozumiane jako:

row_iterator base_iter_begin(col_iterator& bytes[0]); 

I że jedna linia deklaruje funkcję przyjmując za parametr tablica 0 odwołań do col_iterator i zwracających int. Jest to rzeczywiście przypadek most vexing parse, jak wskazano w komentarzach.

Najprostszym sposobem, aby się go pozbyć jest użycie kopii inicjalizacji zamiast bezpośredniego inicjalizacji (inicjalizacji w C++):

row_iterator base_iter_begin = row_iterator(col_iterator(&bytes[0])); 

które w danym przypadku byłoby:

array_iterator::row_iterator base_iter_begin = array_iterator::row_iterator(array_iterator::col_iterator(&bytes[0]), width, pitch); 

UWAGA : Pod warunkiem, że używasz C++ 11, istnieje even more initialization rules, a możesz użyć inicjalizacji listy, aby pozbyć się zarówno szablonu podstawowego, jak i najbardziej irytującego:

array_iterator::row_iterator base_iter_begin{array_iterator::col_iterator(&bytes[0]), width, pitch}; 
Powiązane problemy