2010-01-17 4 views
26

Ich habe einige Inline-Funktionen in einem Namespace in einer Header-Datei enthalten und bin derzeit nicht in der Lage, sie in eine cpp-Datei zu verschieben. Einige dieser Inline-Funktionen verwenden magische Konstanten, zum Beispiel:Private Konstanten in einem Inline-Namespace-Header ausblenden

Allerdings möchte ich diese magische Konstanten privat machen - irgendwelche Ideen wie? Mein erster Gedanke war also eine anonyme Namespace zu verwenden:

// Foo.h 
namespace Foo 
{ 
    namespace 
    { 
     // 'private' constants here 
     const int BAR = 1234; 
    } 

    inline void someFunc() 
    { 
     // Do something with BAR 
    } 
} 

Dies ist jedoch nicht funktioniert und Foo::BAR ist verfügbar auf jede CPP-Datei, die Foo.h enthält? Gibt es eine Möglichkeit, dies zu tun, ohne eine cpp-Datei für die Implementierung zu erstellen?

Antwort

28

Sie können keine anonymen Namespaces für die Übersetzungseinheit verwenden, in der sie definiert sind (oder in Ihrem Fall enthalten sind).
könnten Sie halten sie in einen detail Namensraum zu bewegen, um den Benutzer zu signalisieren, dass sie interne Details sind:

namespace foo { 
    namespace detail { 
     int magic = 42; 
    } 

    // ... use detail::magic 
} 
+4

Dies ist auch die Konvention Boost verwendet. Es funktioniert gut, solange Sie jedem das einfache "Niemals einen Detail-Namespace eingeben" sagen, was die meisten ohnehin nicht tun würden. – GManNickG

3

sie in einem speziellen Namensraum Setzen oder sie mit einem Projekt Konvention speziell, kombiniert nennen, dass solche Dinge nicht sind -public:

namespace foo { 
    namespace detail { // as in "implementation details" 
    inline int answer() { return 42; } 
    const int perfect = 28; 
    } 
    std::string _question(); // not part of foo's "public interface" by convention 

    int this_is_public() { 
    using namespace detail; // now don't have to prefix detail:: 
    return answer() + perfect + _question().length(); 
    } 
} 

jeder Namen dokumentiert als nicht-öffentlich verwendet wird umgehen alle „Schutz“ Sie versuchen; was die wirkliche Sorge hervorhebt: zu dokumentieren, was Teil der öffentlichen Schnittstelle ist und auf die man sich verlassen kann.

Unbenannte Namespaces lösen ein anderes Problem: Namen erhalten, die für eine bestimmte TU eindeutig sind. Sie werden hier nicht helfen.

16

Wie wäre:

namespace Foo { 
    class foo_detail { 
    private: 
     enum { 
      BAR = 1234, 
     }; 

     friend void someFunc(); 
    }; 

    inline 
    void someFunc() { 
     // something with foo_detail::BAR 
    } 
} 

Diese die Konstante nonaccessible für jedermann macht anderes als die Funktionen, die Sie als Freunde markieren. Sie können die Klasse nicht-konstruierbar machen, indem Sie den Konstruktor privat machen, um sicherzustellen, dass niemand versucht, die Klasse zu installieren.