2009年11月17日火曜日

operator<<のオーバーロード

Check
またハマってしまった…。環境はVC++2008です。

ある名前空間内で宣言されたクラスにおいて、operator<<をオーバーロードして標準出力にクラス内の情報をを出力したいと思ったわけですよ。

コードにするとこんな感じ。

namespace hoge
{
class aho
{
public:
  friend std::ostream &operator<<(std::ostream &os, const aho &a);
};
}//!hoge

//以下の記述(というか記述場所)が誤り
std::ostream &operator<<(std::ostream &os, const hoge::aho &a)
{
    return os << "aに関係した何か";
}


ここでなにを勘違いしたのか、私は上記の関数の実装をグローバル空間で行ってしまった。結果は当然、

namespace.cpp(20) : error C2593: 'operator <<' があいまいです。
namespace.cpp(12): 'std::ostream &operator <<(std::ostream &,const hoge:
:aho &)' の可能性があります。
namespace.cpp(6): または 'std::ostream &hoge::operator <<(std::ostream &,const hoge::aho &)' [引数依存の照合を使用して検出しました] の可能性があります
引数リスト '(std::ostream, hoge::aho)' を一致させようとしているとき
 そんな関数ありませんよ、と怒られてしまった。

こんなアホな間違いをする人間はなかなかいないようで、ググってもそれらしき解決策は見当たらない。が、世界レベルだと同じことをやらかす方もいらっしゃるようで、ようやく解決。

早い話が、hogeという名前空間内で宣言したクラスにおいてfriend関数を宣言したならば、その実装もhogeの中でやれってことだそうです。以下ちゃんとコンパイルできたコード。

namespace hoge
{
class aho
{
public:
    friend std::ostream& operator<<(std::ostream &os, const aho& a);
};

//hogeの中で実装するのが正解
std::ostream &operator<<(std::ostream &os, const hoge::aho &a)
{
    return os << "('A`)";
}
}//!hoge
言い訳ではないですが、operator<<ってなんかグローバルな演算子な気がしてですね…。そのくせ、普段operator=とかoperator*とかは平気でメンバ関数として実装してるわけですが…。自分のアホさに辟易させられた小一時間でした。こんなミスする人は滅多にいないでしょうが、何かの役に立てば幸いです…。

0 件のコメント:

コメントを投稿