名前空間の不思議

cppll の ML を読んでいると面白い話題が挙がっていたので,それについて.久々に,プログラミングのお話です.


まず,グローバルの名前空間で次のような関数(演算子)を定義します.

template 
std::ostream& operator<<(
    std::ostream& stream,
    const std::pair& item)
{
    return stream << item.first << ' ' << item.second;
}

そして,その定義した演算子を使って次のようなコードを書きます.

typedef std::pari item;
std::vector participation;

std::copy(participation.begin(), participation.end(),
    std::ostream_iterator(std::cout, "\n"));

そうすると,事前に演算子を定義したはずなのに,コンパイルエラーが出るそうです.


それで,何が問題だったのかというと,どうやら名前空間が問題だったという結論に落ち着いていました.std::copy() の中で,上記の演算子をコールすると std 名前空間の中でその関数(演算子)を探します.それで,今回のケースだと,std 名前空間の中に operator<<(int) のような演算子は存在しているため,グローバルな名前空間で定義した上記の演算子は見えなくなるそうです(途中で誰かが返信していたstd 名前空間オーバーロードのためには開けないが一番しっくりとした説明になるのでしょうか).これが,std 名前空間に存在しないような名前の関数 (例えば,std::ostream& myfunc(std::ostream& stream, const std::pair& item) {} とか)だと,コンパイルは通るようです.いつか引っかかりそうで,怖いなぁというお話でした.


cppll,流し読み位しかしてないんですけど結構面白い話題が挙がっていたりして良いですね.長く続いているだけのことはあるなぁと.