2010-04-10 62 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

相關問題