C++ 为什么endl(std::cout)要编译

C++ 为什么endl(std::cout)要编译,c++,argument-dependent-lookup,C++,Argument Dependent Lookup,令人惊讶的是,下面的代码在各种编译器和版本上编译并运行时没有错误 #include <iostream> int main() { endl(std::cout); return 0; } 将失败,除非使用using,或者您需要std::endl此行为称为或Koenig查找。该算法告诉编译器,在查找非限定的函数调用时,不仅要查看局部范围,还要查看包含参数类型的名称空间 例如: namespace foo { struct bar{ int a; }

令人惊讶的是,下面的代码在各种编译器和版本上编译并运行时没有错误

#include <iostream>

int main() {
    endl(std::cout);
    return 0;
}
将失败,除非使用
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
}

关于问题文本中提到的代码:

endl
std::endl
std
命名空间中声明:

cout
std::cout

所以调用
std::endl(std::cout)非常好

现在,当我们调用endl(std::cout)时
,因为参数
cout
的类型来自
std namespace
,所以在
std
命名空间中搜索一个函数
endl
,并成功地找到它并确认它是一个函数,从而调用限定函数
std::endl


进一步阅读:


  • 为什么在语句“std::cout中使用“std::endl”时需要命名空间限定?这是流操纵器的工作方式。
    操纵器是传递给操作员的函数,我想问题是为什么函数调用中不需要
    std::
    form@Matt麦克纳布:我重读了这篇文章,似乎你是对的
    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
    }
    
    template< class CharT, class Traits >
    std::basic_ostream<charT,traits>&     endl( std::basic_ostream<CharT, Traits>& os );
    
    std::ostream& endl (std::ostream& os);
    
    extern std::ostream cout;
    
    template <class charT, class traits>
    basic_ostream<charT,traits>& endl(basic_ostream<charT,traits>& os);
    
    ostream& ostream::operator << ( ostream& (*op)(ostream&));
    
    return (*endl )(*this);
    
    std::cout << std::endl;
    
    std::endl( std::cout );
    
    endl( std::cout );
    
    ( endl )( std::cout );