namespaceの落とし穴




・namespace内のdefine

namespaceでdefineを括った場合、そのdefineはその名前空間内で宣言されたものとは扱われない。

list-1
namespace ZZZ {
#define XXX 5
}

int x = XXX; // アクセスできちゃうよーん


何故こんなダサい仕様になっているのかわからないが、defineはプリプロセッサでの処理で、そのプリプロセッサにあまり負担をかけたくなかったのだろう。

・名前の重複

他の人が同じ名前空間名を使用しないとも限らない。
ある程度長い名前をつけて、それをaliasして使うほうが良いだろう。

list-2
namespace XXXYYYZZZ {
    namespace AAABBBCCC {
        const int xyz = 1;
    }
}

namespace myspace = XXXYYYZZZ::AAABBBCCC;

void f(){
    int x = myspace::xyz;
}


・ライブラリ等はnamespaceで囲む習慣をつける

namesapceで囲まれていないクラス名は、グローバル(?)であって、他の同名のクラスを許しません。

もし、namespaceで囲ってあれば、

list-3
namespace XXX { class A {}; }
namespace YYY { class A {}; }

using namespace XXX;
using namespace YYY;


とした場合、using namespaceではそのスコープに名前を追加するわけではないので、

list-4
    A a;        //  あいまいエラーになるが、
    XXX::A  a;  //  これはok
    YYY::A  a;  //  これもok


このように、名前空間名を指定してやれば適切なクラスを選択できる。(ので、複数のライブラリをクラス名の競合なくコンパイルすることが出来る)

・事前のusing namespace宣言

同じ名前を持つnamespaceは分散して存在してもいいというのは、とても素晴らしい機構だと言える。クラスに関しても、このように分散させて記述できれば、素晴らしいことが出来る(かも知れない) たとえば、

MixJuice:
http://staff.aist.go.jp/y-ichisugi/ja/mj/
に、その可能性を見出すことが出来る。

それはさておき、複数の同名のnamespaceを使う場合、それを事前にusingしておきたいということがある。

list-5
    using namespace yaneSDK3rd;


このように書いた場合、yaneSDK3rdというnamespaceをひとつでも書いていないとコンパイルエラーになる。事前にダミーのnamespaceを書くことで、この問題を回避できる。

list-6
    namespace yaneSDK3rd {}
    using namespace yaneSDK3rd;


・namespaceの実装の書き方

list-7 doodle.h
namespace doodle
   {
   void f();
   }


list-8 doodle.cpp
#include "doodle.h"
void doodle::f()
   {
   // ...
   }


と書く以外の方法を考えてみる。実装のほうは、次のように書いても同じである。

list-9 doodle.cpp
namespace doodle {
void f()
   {
   // ...
   }
}


こう書くことで、既存のソースの先頭と末尾に'namespace 名前 { 'と'}'を追加することによって、一括してnamespaceに閉じ込めることが出来る。