2014-11-05 7 views
7

Recentemente ho answered a question che fare con una violazione di draft C++14 standard: N4140 sezione 3.3.7Classe portata paragrafo 1 regola 2 che dice:La regola 3 nella sezione 3.3.7/1 di N3936 è ridondante?

Un nome N utilizzato in una classe S si riferiscono alla stessa dichiarazione nel suo contesto e quando rivalutato nell'ambito di applicazione di S. No diagnostico è richiesto per una violazione di questa regola.

al momento pronunciarsi 3 sembrava anche rilevante e dice:

Se riordino dichiarazioni di membro in una classe produce un programma alternativo valido punto (1) e (2), il programma è malato -formato, nessuna diagnostica è richiesta .

La mia reazione iniziale è che regola 3 sembra ridondante ed è in realtà solo un chiarimento della regola 2 e non copre tutti i casi non ancora coperti. Un riordino che risulta in un programma valido alternativo dovrebbe anche violare la regola 2.

Quindi la regola 3 è ridondante oppure esistono casi limite che richiedono entrambe le regole?

risposta

8

Secondo Defect Report 1875: Reordering declarations in class scope regola 3 è ridondante e la soluzione proposta è quello di rimuovere regola 3, si dice:

La necessità di regola # 3 non è chiaro; sembrerebbe che qualsiasi riordino altrimenti valido dovrebbe violare la regola n. 2 al fine di fornire un'interpretazione diversa a . Presa alla lettera, anche la regola n. 3 si applica semplicemente al riordino dei membri di dati non statici senza alcuna dipendenza di nome . Può essere semplicemente rimosso?

e la soluzione proposta è:

Eliminare la terza voce di 3.3.7 [basic.scope.class] paragrafo 1 e rinumerare gli elementi successivi

Anche se questo difetto il rapporto sembra confermare la mia iniziale sospettosa che mi rimane una sensazione fastidiosa che forse la regola 3 è un po 'più ampia dopo tutto. Sezione 3.3.7 include il seguente esempio:

enum { i = 1 }; 

class X { 
    char v[i]; // error: i refers to ::i 
      // but when reevaluated is X::i 
    int f() { return sizeof(c); } // OK: X::c 
    char c; 
    enum { i = 2 }; 
}; 

che viola sia regola 2 e 3 ma un piccolo ritocco:

enum { i = 1 }; 

class X { 
    enum { i = 2 }; 
    char v[i]; // no longer refers to ::i 
       // but reordering can cause it to refer to ::i again 

    int f() { return sizeof(c); } // OK: X::c 
    char c; 
}; 

sembra violare non è più regola 2 ma sicuro sembra violare regola 3. Considererei questo esempio di codice come problematico poiché un riordino dei membri potrebbe facilmente causare il ritorno del codice in violazione della regola 2, ma non è necessaria alcuna diagnostica per indicare ciò che rende questo codice piuttosto fragile.

Aggiornamento

Per quanto ho capito governare 3 non si applica a questo esempio citato da Casey nel commento:

class X { int a; int b; }; 

perché, anche se non v'è più di un ordinamento valido questo caso non rientra in entrambe le regole 1 e 2 quale regola 3 richiede:

alternate programma valido sotto (1) e (2)

+0

Non sono d'accordo con l'affermazione che l'ultimo esempio di codice non è desiderabile. Potrebbe non essere il miglior stile, ma scrivere programmi nel grande richiede che il codice locale sia isolato in una certa misura dalle modifiche al resto del programma. Richiedere a questa classe di dichiarare 'v' come' char v [X :: i]; 'essere ben formati sembra oneroso. Povero stile o no, non sono certo d'accordo sul fatto che il programma debba avere un comportamento indefinito ("malformato, NDR"). – Casey

+0

@Casey Sei d'accordo sul fatto che il primo caso non sia desiderabile? –

+1

Sono d'accordo con questa risposta. –