読者です 読者をやめる 読者になる 読者になる

using と using namespace

C++

Twitterでこういうコードを見かけた。

#include <utility>
 
namespace N {
	using namespace std;
	class C {};
	void swap(C&, C&) {}
	void f() {
		int n1 = 1;
		int n2 = 2;
		swap(n1, n2); // compile Error
	}
}
 
int main() {
	N::f();
	return 0;
}

これはコンパイルエラーになる。だが、using namespace std;を using std::swapにすると正しく動く。それはなぜか。
using declaration(using std::swap)は現在のコンテキスト内にswapを提供する(この場合N内)が、using directive(using namespace std)はグローバルnamespace、すなわちglobal namespace(::)にstd名前空間内の変数やら関数が提供される。
コードに戻ろう。もし仮にusing namespace std;としていた場合を考える。swap(n1, n2)が呼ばれたタイミングでは、まずnamespace N内のswapを照会する。そして、今回それが見つかる。こうなるとここでLookupはおしまい、つまりglobal namespaceまでswapを見に行かないので、std::swapがそもそも候補に入ってない。結果、swap -> C& -> C& -> void が呼ばれてCompile Errorになる。
using std::swapとすれば、std::swapがN名前空間内に提供されるので、std::swapが正しく呼び出される。なのでコンパイルが通る。

確かこんな挙動だったと思いますが、間違ってたら誰か教えてください。