2010-04-10 72 views
4

下面的代码给出了一个错误只是std::endl运算符<<不能输出std :: endl - 修复?当它应该输出

#include <iostream> 
#include <sstream> 

struct MyStream { 
    std::ostream* out_; 
    MyStream(std::ostream* out) : out_(out) {} 
    std::ostream& operator<<(const std::string& s) { 
    (*out_) << s; 
    return *out_; 
    } 
}; 

template<class OutputStream> 
struct Foo { 
    OutputStream* out_; 
    Foo(OutputStream* out) : out_(out) {} 
    void test() { 
    (*out_) << "OK" << std::endl; 
    (*out_) << std::endl; // ERROR  
    } 
}; 

int main(int argc, char** argv){ 
    MyStream out(&std::cout); 
    Foo<MyStream> foo(&out); 
    foo.test(); 
    return EXIT_SUCCESS; 
} 

的错误是:

stream1.cpp:19: error: no match for 'operator<<' in '*((Foo<MyStream>*)this)->Foo<MyStream>::out_ << std::endl' 
stream1.cpp:7: note: candidates are: std::ostream& MyStream::operator<<(const std::string&) 

因此,它可以输出字符串(请参阅上述错误线),但不只是std::endl,大概是因为std::endl不是字符串,但operator<<定义要求输入一个字符串。

模板的operator<<没有帮助:

template<class T> 
    std::ostream& operator<<(const T& s) { ... } 

我怎样才能使代码工作?谢谢!

回答

8

您需要添加到您的struct MyStream

std::ostream& operator<<(std::ostream& (*f)(std::ostream&)) 
    { 
     return f(*out_); 
    } 

std::endl是追加一个换行符并刷新基础流的功能;此函数签名接受该函数并将其应用于ostream成员。

然后,作为一个测试,确定foo::test作为

void test() { 
    (*out_) << "start"; 
    (*out_) << std::endl; 
    (*out_) << "done"; 
    } 

能正确输出

 
start 
done 
+1

谢谢,这是相当疯狂的。人们应该如何知道这一点?应该有一些可以从中衍生出来的类会自动添加这样难看的东西。 – Frank 2010-04-10 03:43:48

+0

重载iostream操作符时要记住的事情是const char *和这个函数指针。这是因为C++模板系统有一些关于指针类型的特殊规则。 (他们是模棱两可的,我想?) – 2010-04-10 03:49:07

+0

@dehmann:我有**没有**的想法,任何人都应该知道这一点。我不得不尝试一些不同的谷歌搜索来让*指向正确的方向,然后我必须将答案拼凑在一起。希望这可以帮助更多的人在这种情况下。 – 2010-04-10 03:51:38

相关问题