using と using namespace
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が正しく呼び出される。なのでコンパイルが通る。
確かこんな挙動だったと思いますが、間違ってたら誰か教えてください。