2012-01-05 13 views
7

Più o meno ciò che suggerisce il titolo. Mentre sono not yet using C++0x mi piacerebbe essere preparato per quando succede, e vorrei anche ridurre la quantità di codice che devo riscrivere per utilizzare alcune delle sue funzionalità. In questo modo posso ottenere la compatibilità all'indietro e in avanti in una volta sola."Backporting" nullptr a C++ - programmi pre-C++ 0x

Uno dei più interessanti che ho trovato è nullptr, che ho usato più spesso di recente.

Dopo aver controllato la "Soluzione alternativa ufficiale" e Meyer's suggestion, ho deciso che mi piacerebbe utilizzarlo sia nel mio C++ che nei futuri programmi C++ 0x. La seconda parte è semplice: essendo una parola chiave, sarà semplicemente supportato il nullptr. Ma la prima parte mi sta causando un certo disagio.

La Meyers funzioni propositive come questo:

class nullptr_t { // ← this is my issue 
    // definition of nullptr_t 
} nullptr = { }; 

Il problema con tale proposta è che dichiara il tipo di essere dichiarato come std::nullptr_t come richiesto dal C++ 0x. Il che significa che la soluzione alternativa per "sentirsi nativi" deve essere eseguita riaprendo lo spazio dei nomi std:: per aggiungere un tipo. Ho la comprensione che è illegale fare in un programma C++ (a differenza dell'aggiunta delle specializzazioni che è apparentemente aggrottare-e-lasciar-andare-con-un-avvertimento).

Desidero utilizzare nullptr in un modo comodo E in un programma C++. Una possibilità avevo pensato stava dichiarando il tipo in un altro spazio dei nomi e poi portarlo nel usando using:

namespace mylibrary { 
class nullptr_t { 
    .... 
} nullptr = { }; 
// end namespace 
} 

// These would have to go in the header file. 
using mylibrary::nullptr; 
using mylibrary::nullptr_t; // apparently this is necessary as well? 

Questo sarebbe il modo corretto per farlo funzionare? Imporrebbe le direttive using, che impone anche un ordine specifico delle direttive #include. Avrei ragione ad aspettarmi che nessun codice pre-C++ 0x richiederebbe il tipo nullptr_t con namespace (come un tipo di argomento di funzione, ad esempio)? Funzionerebbe davvero "sentirsi nativo" se è fatto in questo modo?


Come un addendum, è una accolto o visto di buon occhio cosa da provare e un backport alcuni nifty C++ 0x cose a C++ per una migliore compatibilità e la codifica? Nel frattempo ho integrato questa soluzione e altre che sto lavorando su in a piece of software to be released.

risposta

0

Il motivo principale che non è permesso di aggiungere cose da namespace std è in modo da non complicare le cose che sono già lì. Questo potrebbe altrimenti essere facilmente fatto. Qualcosa che ho trovato in passato erano più definizioni per gli operatori di output per i contenitori istanziati con un tipo predefinito come std::vector<int>. Tuttavia, nullptr_t non è definito in questo spazio dei nomi e l'aggiunta di typedef dovrebbe essere abbastanza innocua. Cioè, definirei nullptr_t in uno spazio dei nomi diverso da namespace std e quindi aggiungere un typedef per nullptr_t a namespace std. La variabile nullptr deve essere dichiarata comunque nell'ambito globale poiché viene utilizzata non qualificata in C++ 2011.

Se il tipo std::nullptr_t è necessario dipende dal fatto che siate interessati ad aggiungere le firme utilizzando questo tipo. Ad esempio, std::shared_ptr<T> può essere confrontato con nullptr. Per questo, è necessario aggiungere sovraccarichi appropriati che menzionino il tipo std::nullptr_t (o utilizzare un altro nome per questo tipo).

+0

Ho sempre pensato che il motivo per cui non è possibile aggiungere cose a 'namespace std' non è così che non si incasinano le cose che ci sono, ma in modo che il codice si compili su molti compilatori (chi potrebbe usare il nome tu scelto), e così continua a compilare quando lo standard aggiunge roba allo spazio dei nomi 'std'. –

+0

(1) Credo che lo spazio dei nomi sia riservato _per l'implementazione_ così, '' è permesso di fare tutto ciò che vuole in 'std'. (2) Questo è così che se il mio codice _solo_ compila con una libreria standard, può essere compilato con tutte le altre implementazioni conformi della libreria standard. (3) Tutti i nomi che terminano con '_t' sono riservati per l'implementazione in C++ 03. –

+0

Da quello che ho capito, la regola del "trattino basso" esiste proprio così che "implementazioni" usano liberamente quei nomi (basta esaminare qualsiasi copia di "", quindi oltre i nomi forniti dallo Standard (come 'cin',' cout') nessun altro nome è riservato nemmeno nello std del namespace, a quel punto un 'typedef' non può danneggiare la compatibilità diretta di una dichiarazione effettiva, eccetto che ci impedisce di aggiungere _too much_ stuff (come" namespace di dettaglio "). –

2

A meno che non si può pensare a una ragione è necessario dichiarare un'altra oggetto di tipo nullptr_t (non posso), mi nascondevo il tipo di distanza e mettere nullptr nel namespace globale per simulare una parola chiave il più possibile :

namespace mylibrary 
{ 
    class nullptr_t 
    { 
     .... 
    }; 
} 

mylibrary::nullptr_t nullptr = { }; 
+1

Sì, nascondere il tipo è ciò che voglio fare. Sono più o meno preoccupato se c'è qualche ragione per cui qualcuno dovrebbe usare il * tipo * 'nullptr_t' per tutto ciò che non può essere fatto semplicemente passando' nullptr' o un tipo di puntatore. –