2013-05-06 6 views
16

È legale dichiarare una variabile di ciclo in un ciclo per cicli con lo stesso nome che utilizzo nell'istruzione espressione del ciclo? Spero che l'esempio chiarisca.Identificatore con lo stesso nome in entrambe le espressioni e dichiarazione di intervallo per

#include <iostream> 
#include <vector> 

struct bar { 
    std::vector<int> nums; 
}; 

int main() 
{ 
    bar b; 
    b.nums = {1, 2, 3}; 

    for(int b : b.nums) 
     std::cout << b << std::endl; 
} 

gcc 4.8 dà un errore mentre clang 3.2 lo consente.

+5

Il [bug è stato segnalato a gcc] (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54430). –

+0

@JesseGood Grazie per averlo scoperto. Ho scoperto che non ho trovato nulla su bugzilla perché stavo cercando "ranged based for" invece di "range based for". Non so come questo termine si sia manifestato nella mia testa, lo stesso errore è accaduto anche nel titolo. – inf

risposta

11

Dalla mia lettura di C++ 2011 6.5.4, il codice di:

bar b; 

for(int b : b.nums) 
    std::cout << b << std::endl; 

devono essere convertiti in:

bar b; 

{ 
    auto && __range = b.nums; 
    for (auto __begin = __range.begin(), __end = __range.end(); __begin != __end; ++__begin) { 
     int b = *__begin; 
     std::cout << b << std::endl; 
    } 
} 

Questo per me significa che clang è corretta.

+0

IMHO, direi che questo è un difetto dello standard. La visibilità di 'int b' dovrebbe essere da': 'fino alla fine dell'istruzione for. – rodrigo

+0

@rodrigo: ho accettato fino a quando ci ho pensato un po 'di più. Cosa significherebbe: 'for (auto & x: x)'? –

+0

Ciò sarebbe privo di significato come la semplice dichiarazione "auto &x = x;" e per gli stessi motivi. – rodrigo

9

Clang è giusto.

Paragrafo 6.5.4/1 della C++ 11 standard definisce la dichiarazione for gamma-based come segue:

Per un gamma basata per dichiarazione della forma

for (for-range-declaration : expression) statement 

let gamma-init essere equivalente all'espressione circondato da parentesi

(expression) 

e per un gamma basata per dichiarazione della forma

for (for-range-declaration : braced-init-list) statement 

lasciare gamma-init essere equivalente al-init-list rinforzato. In ogni caso, una gamma-based per istruzione è equivalente di

{ 
    auto && __range = range-init; 
    for (auto __begin = begin-expr, 
      __end = end-expr; 
      __begin != __end; 
      ++__begin) { 
     for-range-declaration = *__begin; 
     statement 
    } 
} 

Da quanto sopra, è visibile quella variabile b, che corrisponde alla for-range-declaration, viene dichiarata all'interno di un'istruzione blocco nidificato, mentre la l'inizializzatore range-init (che corrisponde a b.nums) viene visualizzato nell'oggetto principale, dove b deve essere risolto nell'oggetto di tipo bar.

+0

Ma il 'b' in * range-init * sarà il' b' sbagliato. –

+0

@sftrabbit: hai ragione, inizialmente l'ho ignorato. Ho modificato la risposta, grazie –

+3

Non è così semplice ... da un'interpretazione letterale dello standard, in 'auto && __range = range-init;' 'range-init' è in realtà' b.num', ma il 'int b' non entra nella definizione fino a 5 righe dopo ...Ma ancora, vedendo il codice originale, ci si aspetterebbe che il 'int b' nasconda la' bar b'. – rodrigo

2

Per quello che vale, questo bug è stato corretto sul trunk gcc. :)

+0

Ottimo per sentire: D – inf