web-dev-qa-db-ja.com

インライン名前空間ヘッダーでプライベート定数を非表示にする

ヘッダーファイルの名前空間内にいくつかのインライン関数が含まれていますが、現在、それらをcppファイルに移動することはできません。これらのインライン関数の一部は、次のようにマジック定数を使用します。

// Foo.h
namespace Foo
{
    const int BAR = 1234;

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

ただし、これらの魔法の定数を非公開にしたいのですが、どのようにアイデアがありますか?私の最初の考えは、匿名の名前空間を使用することでした。

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

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

ただし、これは機能せず、Foo::BARを含むすべてのcppファイルでFoo.hを使用できますか?実装CPPファイルを作成せずにこれを行う方法はありますか?

29
Rob

匿名の名前空間は、それらが定義されている(またはケースに含まれている)翻訳単位に対して機能することはできません。
それらをdetail名前空間に移動して、内部の詳細であることをユーザーに通知することを検討できます。

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

    // ... use detail::magic
}
30
Georg Fritzsche

どうですか:

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

        friend void someFunc();
    };

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

これにより、友達としてマークした関数以外のユーザーは定数にアクセスできなくなります。コンストラクターをプライベートにして、誰もクラスをインスタンス化しようとしないようにすることで、クラスを構築不可能にすることができます。

18
villintehaspam

それらを特別な名前空間に配置するか、特別な名前を付けて、そのようなものは非公開であるというプロジェクト規則と組み合わせます。

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();
  }
}

非公開として文書化された名前を使用している人は誰でも、あなたが試みる「保護」を回避します。これは本当の懸念を浮き彫りにします:パブリックインターフェースの一部であり、信頼できるものを文書化することです。

名前のない名前空間は、特定のTUに固有の名前を取得するという別の問題を解決します。彼らはここでは役に立ちません。

3
Roger Pate