2015-11-05 39 views
1

我們知道endl是操縱器,它在內部將'\n'放入緩衝區,然後刷新緩衝區。 endl在哪裏定義?什麼是endl,它是宏還是函數或變量,類還是對象?我怎樣才能定義我自己的endl操縱器?endl操縱器在哪裏定義

+0

的'的std :: endl'操縱器在''頭中定義。 – 101010

+0

在ENDL的定義,現在看來似乎是函數,那麼爲什麼我們不傳遞任何參數時,我們用它來與COUT模板<類圖,類性狀> 的std :: basic_ostream <圖表,性狀>&ENDL(STD :: basic_ostream <圖,性狀> & os); –

+0

我試圖澄清的問題,我認爲這裏有一個很好的問題,它已經吸引了來自Yakk一個很好的答案。 –

回答

13

std::endl是簽名的函數的模板:

template<class CharT, class Traits> 
std::basic_ostream<CharT,Traits>& endl(std::basic_ostream<CharT,Traits>&); 

std::basic_ostream::operator<<過載std::basic_ostream<CharT,Traits>>::operator<<(std::basic_ostream<CharT,Traits>& (*func)(std::basic_ostream<CharT,Traits>&))接受某個簽名的函數。

當你這樣做std::cout << std::endl,重載決策上std::endl,這就決定了正確的模板類型std::endl和實例化一個函數來完成。然後這個衰減到一個指針,並傳遞到operator<<

std::basic_ostream::operator<<然後調用有問題的ostream上的函數,並返回返回值。喜歡的東西:

template<class CharT, class Traits> 
std::basic_ostream<CharT, Traits>& 
std::basic_ostream<CharT, Traits>::operator<<(
    std::basic_ostream<CharT,Traits>& (*func)(std::basic_ostream<CharT,Traits>&) 
) { 
    return func(*this); 
} 

但具體實施起來編譯器庫作家。

std::endl會導致打印換行符,然後通知ostream自行刷新。您可以通過的這兩行代碼仿真RLS做std::cout << std::endl;

std::cout.put(std::cout.widen('\n')); 
std::cout.flush(); 

究竟如何std::endl實現高達編譯器,但上面的是你會如何寫呢(當然在通用流)一個體面的近似。

如果您保證可以訪問std::endl#include <ostream>。如果您包含來自std庫的任何其他頭文件,則您可以訪問它。什麼文件準確地定義它是再次實施。

std::endl被稱爲「io操縱器」。這種技術旨在允許通過將<<調用鏈接在一起來將操作io流狀態的函數與輸出命令「內聯」設置。

要創建您自己的,如果您希望它可以與單一類型的ostream一起使用,只需創建一個引用該類型ostream的函數,然後通過引用將其返回。它現在是一個io操縱者。

如果要處理一組流,創建一個模板:

template<class CharT, class Traits> 
std::basic_ostream<CharT, Traits>& bob(std::basic_ostream<CharT, Traits>& os) 
{ 
    return os << os.widen('b') << os.widen('o') << os.widen('b'); 
} 

現在是一個IO用操縱打印"bob"。它可以做任何你想要的問題basic_ostream

一種替代方案是這樣的:

struct bob_t { 
    template<class OS> 
    OS& operator()(OS& os)const { 
    return os << os.widen('b') << os.widen('o') << os.widen('b'); 
    } 
    template<class OS> 
    operator OS&(*)(OS&)() const { 
    return [](OS& os)->OS&{ return bob_t{}(os); }; 
    } 
}; 
static const bob_t bob; 

其中bob現在是可被用作一個IO操縱器的對象。


<<過載是A->(A->A)->A類型的函數。基本上,不是將X傳遞給f,而是將X和f傳遞給<<,然後執行f(X)。純粹的語法糖。

事實上,std::endl是一個模板意味着完美轉發這是一個有點疼痛,由於這種技術。我最終定義無國籍功能endl_t類型,與過載operator basic_ostream<CharT,Traits>&(*)(basic_ostream<CharT,Traits>&)()const,所以有時可以通過完美的轉發代理重載集合。

然後我們可以將整個過載集合f:(A->A)傳遞給<<,並讓「下一層下來」解決過載問題。

+1

這是一個完全真棒答案,不知道爲什麼這是不接受的答案。 –

+0

權沙菲克Yaghmour ,很抱歉太晚/ –

3

http://en.cppreference.com/w/cpp/io/manip/endl說:

在頭<ostream>

template< class CharT, class Traits > 
std::basic_ostream<CharT, Traits>& endl(std::basic_ostream<CharT, Traits>& os); 

,如果我想編寫自己ENDL手,我將不得不寫什麼代碼定義?

如果你想創建僅供std::ostream剛剛創建接受參考std::ostream,並返回一個函數。如果你想使其具有通用性,你可以使其模板化,如std::endl

+0

所以看起來它是功能,如果是,那麼爲什麼我們不傳遞任何參數呢? –

+0

@NiravsinhParmar becase的是內部完成重載'運營商<<'接受某個簽名的功能。 – Slava