以下のようなDebugクラスを作成したのですが、
Debug::operator<<にstd::endlを渡すとコンパイルエラーになります。
どのように修正したらよいでしょうか?
#include <iostream>
using namespace std;
class Debug {
public:
template <class T>
Debug& operator<<(const T& a) {
// デバッグ時のみ std::cout << a を実行する
std::cout << a;
}
};
int main() {
Debug d;
d << "foo" << 100 << '\n'; // 問題なし
d << std::endl; // コンパイルエラー
}
コンパイルエラーメッセージ:
no match for 'operator<<' in 'd << std::endl'
g++ 3.4.4 cygwin
あれ、Debug::operator<<で戻り値を返していないのにコンパイルできた…。
(-Wallをつけてコンパイルしたら警告がでた…)
すみません。以下のように修正します。
#include <iostream>
class Debug {
public:
template <class T>
Debug& operator<<(const T& a) {
std::cout << a;
return *this; // ここを修正
}
};
int main() {
Debug d;
d << "foo" << 100 << '\n'; // 問題なし
// d << std::endl; // コンパイルエラー
}
std::endlが単なる関数ではなく、関数テンプレートだからです。
std::endlのプロトタイプは
template<class charT, class traits>
basic_ostream<charT, traits>& endl(basic_ostream<charT, traits>&);
となっています。(名前空間stdは省略)
単純に
template<class T> Debug& Debug::operator<<(const T& a)
にstd::endlを渡しただけでは、charTとtaritsを推論できないので
コンパイルエラーになります。
template<class T> Debug& Debug::operator<<(std::ostream& (*pf)(std::ostream &))
{
std::cout << pf;
return *this;
}
というoperator<<を定義すればstd::endlやその他各種マニピュレータが
とりあえず使えるようになります。(よい解かどうかは別として)
もし、Debugの用途がデバッグ出力用のクラスだとしたら、Debugを
std::ostreamから派生させて、さらに低レベル出力用クラスとして
std::streambufの派生クラスを定義するとか。
て、大掛りすぎるか……
間違い訂正。
> template<class T> Debug& Debug::operator<<(std::ostream& (*pf)(std::ostream &))
これ、テンプレート関数にする必要はありません (Tの使いどころなし)。
正しくは
Debug& Debug::operator<<(std::ostream& (*pf)(std::ostream &))
です。
yoh2さん、ありがとうございました。
ツイート | ![]() |