2009年11月14日土曜日

templateクラスでoperator<<をオーバーロード

templateクラスHogeのインスタンスfugaを、
1Hoge<int> fuga;
2std::cout << fuga << std::endl;
みたいに出力しようと思えばoperator<<をオーバーロードする必要があります。
んで、
01#include <iostream>
02using namespace std;
03 
04template<class T>
05class Hoge{
06public:
07    friend ostream &operator<<(ostream &os, const Hoge &h);//decl※実はここが間違い
08   T elem;
09};
10//impl
11template<class T> ostream &operator<<(ostream &os, const Hoge<t> &h){
12    return os << h.elem;
13}
とか書いてみたところ見事にリンクエラーを食らってしまった。
error LNK2019: 未解決の外部シンボル "class std::basic_ostream<char,struct std::char_traits><char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits><char>> &,class Hoge<int> const &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ABV?$Hoge@H@@@Z) が関数 _main で参照されました。
要するにヘッダに宣言したoperator<<(declのところ)と、実装したoperator<<(impl)が別物だと解釈されているようだ。

色々試してみたところ宣言部に間違いがあったようで、正しくは以下のようになります。
1template<class T>
2class Hoge{
3  //関係ないところは省略
4  friend ostream &operator<<<T>(ostream &os, const Hoge &h);
5};
ほとんどの部分が一緒なんですが、よーく見てみると、operator<<の後ろに<T>なる文字が入っています。マジわかりづらい。

テンプレートは便利なんですが、私のような素人にとっては大変な危険も伴う諸刃の剣のように思えてなりません。てか素直にtoStringメソッドでも作ったほうがよかったのかもしれん…。

どうでもいいがこの記事書くのに異様に時間がかかってしまった。理由はエスケープ文字。<やら>やらがたくさん出てくるおかげで&lt;なんかをあちこちに書かなきゃいかんかった。今度からここを使おう
HTMLエスケープ(HTMLエンコード)ツール

0 件のコメント:

コメントを投稿