こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

privateなnamespaceメンバ

namespace内のメンバをprivateのようにしたいときは、無名名前空間を使うとあったのですが、ヘッダオンリーライブラリでこれを実現する方法はありませんか?

紹介されている方法
//hoge.h
namespace Hoge{
void hoge();
}

//hoge.cpp
namespace Hoge{
namespace{
void hogeHelper(){}
}
void hoge(){hogeHelper();}
}

上記の方法ではhoge.cpp以外からはhogeHelperにはアクセスできなくなるとのことです。

しかし、ヘッダオンリーライブラリで次のように書いている場合にHoge::hogeHelperとしてアクセスできてしまいます。

//hoge.h
namespace Hoge{
namespace{
inline void hogeHelper(){}
}
inline void hoge(){hogeHelper();}
}

(ライブラリを書き換えない限り)hogeHelperへのアクセスを禁止する方法はありませんか?

投稿日時 - 2011-07-27 12:53:57

QNo.6902744

暇なときに回答ください

質問者が選んだベストアンサー

まあこの筋だとどうやっても「エラーメッセージがわけわからん」状態になるのは避けられないでしょうねぇ. ソースで
#define DO_NOT_USE_AFTERWARD(name) なんか
のようなマクロを定義して明確にすれば多少「ごまかし」感は減るけど....

あるいは, いっそあきらめて
すべてのメンバーが private かつ static な class
を作るとか. たとえば,
namespace Hoge {
void hoge();
class detail {
static void hogeHelper() { }
friend void hoge();
};
inline void hoge() { detail::hogeHelper(); }
}
みたいなイメージ.

投稿日時 - 2011-07-28 13:10:47

補足

クラスのprivate staticメンバにしてfriend指定するのは思いつきませんでした。
これならエラーメッセージも理解しやすいです。

namespace Hoge内の他の関数やhoge()内から頻繁に使用される共通処理hogeHelper()を単体で外部から呼び出されたくないだけなので、classのprivate staticメンバで十分目的が果たせます。
namespaceのようにメンバを分割して記述できないことと、class名::を書くことを我慢すれば、namespaceにこだわる必要はないですね。

ありがとうございました。

投稿日時 - 2011-07-28 16:54:16

ANo.3

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(3)

ANo.2

手元の g++ で試してみると
namespace Hoge{
namespace{
inline void hogeHelper(){}
}
inline void hoge(){hogeHelper();}
namespace{
inline namespace {
void hogeHelper();
}
}
}
で (「エラーになる」という意味で) 回避できている感じがします. つまり C++0x ならごまかせるかもしれない. そもそも名前空間が「アクセス制御」を意図しているわけじゃないので, 結局は「ごまかし」の感じが強いですが.

投稿日時 - 2011-07-27 14:36:39

補足

hoge()内では1つめのhogeHelper()を参照しつつ、外からは定義されていない2つめのhogeHelper()を参照させるということですね。

inline namespaceはVC++2010ではエラーになってしまいました。

inlineを外した所、外からも1つめのhogeHelper()を参照してしまったらしく、リンクも通ってしまいました。

ここで、2個目のhogeHelper()をnamespace{namespace{}}から外に出してHoge内にしたところ、hoge()からは無名1つめのhogeHelper()を参照し、外からは2つめのhogeHelper()を参照したようで、みごとにリンクエラーにできました。

これはなかなかスマートな方法です。

さらに、リンクエラーではなくコンパイルエラーにするために、2つめのhogeHelper()を、もはや関数ではなく何でも良いのでnamespaceにしてしまいました。

namespace hogeHelper{}

これでHoge::hogeHelperによる関数へのアクセスを完全に禁止できそうです。

ありがとうございました。

投稿日時 - 2011-07-28 11:49:23

ANo.1

可能なら
#define hogeHelper
という技でごまかすとか.

投稿日時 - 2011-07-27 13:45:13

補足

なるほど、そういう手もあるんですね。

回答ありがとうございます。

投稿日時 - 2011-07-27 13:50:04