for_each (begin(a), end(a), [] (int x) { cout<<x<<" ";});
begin(a)
produce un int(*)[3]
(puntatore a matrice di dimensioni [3]), e deferenziandolo produce un int(&)[3]
, mentre l'espressione lambda aspetta un argomento int
.
for_each (begin(a[0]), end(a[2]), [] (int x) { cout<<x<<" ";});
begin(a[0])
produce un int*
che punta al primo elemento nella prima fila di a
e end(a[2])
produce un int*
punta a uno dopo l'ultimo elemento nell'ultima fila di a
, quindi tutto funziona.
Ora per la parte basata su intervallo for
.
Se si rimuove il &
dalla riga for (auto& row : a)
, l'errore si verifica effettivamente nella seguente riga for(auto x : row)
. Questo è dovuto al modo in cui è specificato lo range-based for
. La clausola pertinente al caso d'uso è
Se __range
è un array, quindi begin_expr è __range
e end_expr è (__range + __bound)
, dove __bound
è il numero di elementi nella matrice (se l'array ha dimensione sconosciuta o è di un tipo incompleto, il programma è mal-formato)
Hereon io sarò riferisco alle identificatori citati nel Spiegazione sezione della pagina collegata.
Consideriamo il caso for (auto& row : a)
:
__range
si deduce come int(&)[3][3]
(riferimento alla matrice di dimensioni [3] [3]). __begin
viene quindi dedotto come int(*)[3]
(puntatore a matrice di dimensioni [3]) poiché il tipo di __range
decade in un puntatore alla prima riga dell'array 2D. range_expression è auto& row
, quindi row
viene dedotto come int(&)[3]
(riferimento alla matrice di dimensioni [3]).
Successivamente, lo stesso processo viene ripetuto per il numero interno for
. In questo caso, __range
è int(&)[3]
e si applica la clausola dell'array I citata sopra; il restante processo di deduzione del tipo è simile a quello che ho descritto sopra.
__range = int(&)[3]
__begin = int*
x = int
Consideriamo ora il caso for (auto row : a)
:
__range
, __begin
e __end
sono tutti dedurre lo stesso. La differenza cruciale in questo caso è range_expressionauto row
, che causa il decadimento del tipo int(*)[3]
che __begin
è stato dedotto come. Ciò significa cheviene dedotto come int *
e nessuna delle 3 clausole in cui è descritta la determinazione di begin_expr/end_expr gestisce un puntatore non elaborato. Ciò si traduce in un errore di compilazione all'interno del ciclo nidificato for
.
Capo Thnx! Questa spiegazione è stata molto chiara e concisa! – Anwesha