簡體   English   中英

為什么endl(std :: cout)會編譯

[英]Why does endl(std::cout) compile

令人驚訝的是,以下代碼可以在各種編譯器和版本上編譯並正常運行。

#include <iostream>

int main() {
    endl(std::cout);
    return 0;
}

Ideone鏈接

它如何編譯? 我確信全局范圍內沒有endl ,因為類似

std::cout << endl;

除非using否則將失敗,否則您需要std::endl

此行為稱為自變量依賴查找或Koenig查找。 該算法告訴編譯器在查找不合格的函數調用時,不僅要查看本地范圍,還要查看包含參數類型的名稱空間。

例如:

namespace foo {
  struct bar{
    int a;
  };

  void baz(struct bar) {
    ...
  }
};

int main() {
  foo::bar b = {42};
  baz(b);  // Also look in foo namespace (foo::baz)
  // because type of argument(b) is in namespace foo
}

關於問題文本中引用的那段代碼:

std名稱空間中聲明endlstd::endl ,如下所示

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

要么

std::ostream& endl (std::ostream& os);

並且coutstd::cout 聲明為

extern std::ostream cout;

因此調用std::endl(std::cout); 很好。

現在,當只調用endl(std::cout); ,因為參數cout的類型來自std namespace空間,所以可以在std名稱空間中搜索到不合格的函數endl ,並成功找到該函數並確認它是一個函數,因此調用了合格的函數std::endl


進一步閱讀:

  1. GOTW 30:名稱查找

  2. 在給定參數依賴查找的情況下,為什么在語句“ std :: cout << std :: endl;”中使用“ std :: endl”需要命名空間限定?

這是流操縱器的工作方式。 操縱器是作為參數傳遞給運算符<<的函數。 然后在運算符中將它們簡單地調用。

所以你有函數聲明像

template <class charT, class traits>
basic_ostream<charT,traits>& endl(basic_ostream<charT,traits>& os);

然后將其指針傳遞給運算符<<。 並在運算符中聲明了類似

ostream& ostream::operator << ( ostream& (*op)(ostream&));

該函數稱為.like

return (*endl )(*this);

因此,當您看到記錄時

std::cout << std::endl;

然后std::endl是傳遞給operator <<作為參數的函數指針。

在記錄中

std::endl( std::cout );

名稱endl之前的名稱空間前綴可以省略,因為在這種情況下,編譯器將使用自變量依賴查找。 因此,這個記錄

endl( std::cout );

將成功編譯。

但是,如果將函數名稱括在括號中,則不使用ADL,並且以下記錄

( endl )( std::cout );

將不會編譯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM