2013年11月5日火曜日

C++の名前空間のネストと識別子の衝突と無名名前空間について

私は普段DXライブラリを使っているのだが、 先日、以下の様なコードを書いた所エラーが出た。 ちなみに簡略化された全く意味のないコートであることに留意されたし。

#include "lua.hpp"
#include "DxLib.h"

namespace Lua{
	int Func( lua_State* pLuaState ){
		return 0;
	}
}
namespace DxLib{
	namespace Lua{
	}
}
void Test( void ){
	lua_State* p = NULL;
	Lua::Func( p );
}

エラーの内容は以下のとおり。

error C2872: 'Lua' : あいまいなシンボルです。
'Lua' である可能性があります。
または 'DxLib::Lua'

DXライブラリは、 DxLib.h 内で、名前空間 DxLib を using 宣言している。 このため、名前空間 DxLib::Lua と 名前空間 Lua をコンパイラが区別する事ができず、 コンパイルエラーとなっている。

C++において、普通に宣言した識別子は、無名名前空間(グローバル名前空間とも呼ばれる)に所属している。 無名名前空間に属している事を明示するためには、識別子をスコープ演算子から書き始める。 この記法を用いて修正したコードは以下のとおり。(関数 Test のみ)

void Test( void ){
	lua_State* p = NULL;
	::Lua::Func( p );
}

本当なら、関数 Func は名前空間 Lua にのみ存在するので、参照自体は出来ると思うのだが・・・ もしかしたらVC++ 2010でコンパイル出来ないだけで、他のコンパイラだと通るかもしれない。C++怖い。

ちなみに、以下の様な、識別子を使わない名前空間も無名名前空間と呼ぶ。

namespace{
	...
}

この名前空間内に記述した識別子は、同じソースコード内でしか参照できなくなる。 C++では、 static 修飾子よりも無名名前空間を使用することが推奨されている[要出典]

0 件のコメント: