2016-04-27 47 views
5

Ho ereditato un orribile bit di codice legacy che include circa 1000 righe di definizione di classe di utilità che devono essere visualizzate prima del codice "reale" in un file di origine. Per evitare scontri con altri moduli che potrebbe anche hanno associato le classi precedenti, ho messo la classe di utilità in un namespace anonimo:C'è un solo spazio dei nomi senza nome per unità di compilazione?

namespace { 
    class OldUtils { 
     OldUtils(); 
     int foo(); 
     double bar(); 
    }; 

    OldUtils::OldUtils() { 
     // hundreds of lines 
    } 

    int OldUtils::foo() { 
     // hundreds more lines 
    } 

    ... 
} 

class ActuallyInteresting { 
    // uses OldUtils 
}; 

Ma io preferirei avere il codice ActuallyInteresting che la gente sarà (in realtà) interessati a vicino alla parte superiore del file, ad es a partire dalla riga 50, che a destra in basso, ad es. a partire dalla linea 1000. La suddivisione dell'horrid utility class in un'unità di compilazione separata non è un'opzione, per ragioni di livello superiore a cui non entrerò!

Quindi mi chiedo se sia possibile inserire la dichiarazione della classe breve, senza le definizioni dei metodi, in uno spazio dei nomi senza nome nella parte superiore del file e le definizioni dei metodi molto più lunghe in un altro spazio dei nomi senza nome nella parte inferiore:

namespace { 
    class OldUtils { 
     OldUtils(); 
     int foo(); 
     double bar(); 
    }; 
} 

class ActuallyInteresting { 
    // uses OldUtils 
}; 

namespace { 
    OldUtils::OldUtils() { 
     // hundreds of lines 
    } 

    int OldUtils::foo() { 
     // hundreds more lines 
    } 

    ... 
} 

saranno questi due namespace senza nome "separare" trattati come la stessa portata nell'unità di compilazione, o saranno diversi spazi dei nomi univoci essere generato per ciascuno? Lo standard ha qualcosa da dire su questo?

+0

ogni spazio dei nomi senza nome sarà unico per ogni unità di traduzione (lo stesso statico in un unità di traduzione) –

+0

@ DieterLücking: Se questo è vero, come si fa accesso una variabile globale in uno spazio dei nomi senza nome in un'altra unità di traduzione? Il nome dell'altra unità di traduzione viene aggiunto al testo della risoluzione dell'oscilloscopio? –

risposta

4

Saranno questi due namespace senza nome "separare" trattati come lo stesso ambito entro l'unità di compilazione, o intende namespace diversi uniche essere generato per ciascuno? Lo standard ha qualcosa da dire su questo ?

Sì, saranno considerati uguali all'interno dell'unità di compilazione. E lo standard ha qualcosa da dire ....

Citando il latest standard draft ... (enfasi sono mie)

$7.3.1.1 Un anonimo-namespace definizione si comporta come se fosse sostituito da

inlineopt namespace unique { /* empty body */ } 
using namespace unique ; 
namespace unique { namespace-body } 

dove appare inline se e solo se appare nella senza nome-namespace definizione e tutte le occorrenze diuniquein un'unità di traduzione sono sostituiti con lo stesso identificativo, e questo identificatore differisce da tutti gli altri identificatori nella unità di traduzione

compilare questo breve programma, il compilatore dovrebbe lamentare ridichiarazione variabile ...

namespace { int c = 0; } 
namespace { double c = 8; } 

int main(){ ++c; } 

Tuttavia, per accedere a variabili in uno spazio dei nomi senza nome, si utilizza il modo normale di accedere alle variabili globali ...Quindi funzionerà.

namespace { int c = 0; } 
namespace { void f(){ c = 8; } } 

int main(){ ++c; } 
-2

Si può capire la risposta da soli, semplicemente controllando se il seguente codice compilato:

namespace { 
    int a; 
} 

namespace { 
    int *b=&a; 
} 

si aspetta di ottenere un errore di compilazione, se ogni spazio dei nomi è unico; e questo verrà compilato senza problemi se lo spazio dei nomi senza nome è lo stesso, in entrambi i casi.

+0

Avrei dovuto dire che ho fatto un test di base in questo filone (che sembra funzionare). Ma è garantito dallo standard o da un comportamento non definito dipendente dal compilatore? Grazie – andybuckley

+2

L'uso di un compilatore non rende il codice standard. MSVS compilerà felicemente int & var = some_function_that _retunrs_int() 'che non è standard. – NathanOliver