2014-09-30 19 views
9

in C++ un namespace anonimo è equivalente a:Cosa succede se ho bisogno di spazio dei nomi anonimo in un'intestazione?

namespace $$$$ { 
    //something 
} 
using namespace $$$$; 

Dove $$$$ è una sorta di identificativo univoco. Lo spazio dei nomi anonimo è quindi utile per il codice che non dovrebbe essere visto al di fuori dell'unità di compilazione.

Fin qui tutto bene, ma di recente ho iniziato a scrivere del codice con i modelli, tale codice deve essere nelle intestazioni così utilizzando namespace anonimi non ha molto senso in quanto il semplice inserimento del intestazione annullare l'effetto di isolamento.

Quindi la domanda è, qual è il modo consigliato in questo caso? Ho iniziato a utilizzare un namespace chiamato Private. In realtà non blocca nessuno che voglia utilizzare gli identificatori all'interno, ma almeno riduce le incompatibilità del nome all'id "Privato".

Ci sono modi migliori? Suggerimenti?

+5

AFAIK che tutto si può fare, librerie di template usano spesso spazi dei nomi come 'detail' per questo scopo. – user657267

+0

Idealmente tutto il codice dovrebbe essere in una sorta di spazio dei nomi. Metti i tuoi modelli in una sorta di spazio dei nomi chiamato Utility, o Alpha o MyWork o qualcosa del genere. E metti anche le funzioni di aiuto. –

+0

Grazie user657267; quella era la conferma che stavo cercando. Avevo paura che mi mancasse l'ovvio. –

risposta

3

Stick con il Privatenamespace (o utilizzare il più popolare detail). Ricorda che l'idea principale dei meccanismi di accesso al C++ rende difficile l'abuso, non impossibile. Proteggiti dagli incidenti, non dagli attacchi dannosi.

4

Se sei disperato per quell'isolamento, perché non il buon vecchio file- static? E 'stato undeprecated:

template <typename T> 
static void foo() 
{} 

int main() 
{ 
    foo<char>(); 
} 

Poi di nuovo, se avete solo bisogno foo all'interno di un'unità di traduzione, quindi presumibilmente si sta solo compresa in un colpo di testa all'interno di tale unità di traduzione, e quindi non importa se si tratta di alcun tipo "in un colpo di testa". Quindi, semplicemente non includere i modelli in altre unità di traduzione e hai già ampiamente raggiunto il tuo obiettivo di isolamento.

Per davvero isolamento di garanzia per tutti i possibili istanziazioni (cioè compresi quelli che hai creato all'interno di questa TU), utilizzare static come sopra o semplicemente documentare il vostro intento con uno spazio dei nomi detail.

+0

+1: I modelli devono essere presenti in un'intestazione se si desidera utilizzarli in più TU. –

0

Il modo più usuale per nascondere l'implementazione del codice di modello in un'intestazione consiste nel mettere l'implementazione in uno spazio dei nomi chiamato detail.

Ad esempio:

namespace cpputil { // my c++ utility library namespace 

    namespace detail { // implementation details of this libraries headers go here 

    // a functor private to the library 
    template<class T> 
    struct private_functor { 
     private_functor(const T& t) : _t(t) {} 
     void write(std::ostream& os) const { _t.write(os); } 
    private: 
     const T& _t; 
    }; 

    // an extension to std::ostream::operator<< 
    template<class T> 
    std::ostream& operator<<(std::ostream& os, const private_functor<T>& pf) 
    { 
     pf.write(os); 
     return os; 
    } 
    } 

    /// a public template function that is designed to allow an object to be emitted to a stream 
    /// returns a function object that calls T::write(std::ostream&) when placed into an 
    /// output stream 
    template<class T> 
    detail::private_functor emit(const T& t) { 
    return detail::private_functor<T>(t); 
    } 
} 

// can be used like this: 

int main() { 
    struct S { 
    void write(std::ostream& os) const { os << "{I am an S}"; } 
    }; 

    std::cout << cpputil::emit(S) << std::endl; 
    return 0; 
}