Click on koenig.cpp to get source.
#include <iostream>
// File: koenig.cpp by Erich Kaltofen, March 25, 2026
// ------------------------
// The program analyzes the C++ version
//
// std::cout << "Hello world!" << std::endl;
//
// of the Kernighan-Ritchie C statement
//
// printf("Hello world!\n);
//
// Both << operators are compiled with argument dependent lookup (ADL)
// ------------------------
// We first give the standard ADL (Koenig) lookup example
namespace bar {
class dummy_t {}; // empty encapsulated class for ADL
void foo(dummy_t T, int i) {std::cout << "bar::foo call: " << i << std::endl;}
}// namespace bar
// the template function expansion for std::endl from <ostream> for cout;
// the code not needed, but explains the std::endl output manipulator function
template
std::basic_ostream<char, std::char_traits<char> >&
std::endl(std::basic_ostream<char, std::char_traits<char> >& os);
// program is without "using namespace std;" to exercise ADL
int main(void) {
foo(bar::dummy_t(), 5); // standard argument-dependent lookup example:
// bar::foo() is called because one argument is in the scope bar::
std::cout << "1. Hello world!" // ADL for std::operator<< because
// first argument is in namespace std
// compiles to std::operator<< function
// see 2. below
<< std::endl; // ADL for std::operator<<
// compiles to basic_ostream<...>::operator<<
// template member operator
// see 5.-7. below
// note: std:endl is a function which is run (see 3.-5. below)
// what calls the compiler generates
operator<<(std::cout, "2. Hello world!");
// Note: 1. ADL of operator<< because an argument is in namespace std.
// std::operator<< is defined for second argument type const char[]
// 2. there is a second possible match with the
// templated basic_stream<...>::operator<< (void* T); see 7. below.
//
// The template function for std::operator<<, namely,
//
// template<typename _CharT, typename _Traits>
// inline basic_ostream<_CharT, _Traits>&
// operator<<(basic_ostream<_CharT, _Traits>& __out, const _CharT* __s)
//
// is used because the argument type const char* is more specialized
// (template specialization for template function operator<<)
// Compare with 6. below
std::cout.operator<<(std::endl); // explicit call with endl function pointer
// this is to what std::cout << std::endl; compiles. There is no definition
// for the template function std::operator<< with a second argument type a
// pointer to a function, std::endl, but there is one for the
// template member function
//
// __ostream_type&
// basic_ostream<...>::operator<<(ios_base& (*__pf) (ios_base&))
// { __pf(*this); return *this; }
// call with fully scoped and template expanded endl function
std::operator<<(std::cout, "3. Hello world!");
std::cout.operator<<(std::endl<char, std::char_traits<char> >);
// using endl as a function
std::cout << "4. Hello world!";
endl(std::cout); // explicit call to std::endl template function
// ADL look-up: no function endl in global scope
// But there is a template function in namespace std
std::cout << std::basic_string<char>("5. Hello world!");
// note: cannot do std::cout.operator<<(std::basic_string<char>("Hello"));
// because argument type is not defined in member operator
std::cout.operator<<(std::endl); // explicit call with endl function pointer
std::cout << "doing std::cout.operator<<(\"6. Hello world!\") ";
std::cout.operator<<("6. Hello world!"); // prints pointer address
// template operator<< member operator has pointer argument type
//
// __ostream_type& basic_ostream<...>::operator<<(const void* __p)
// { return _M_insert(__p); }
//
// and then prints the pointer in hexadecimal.
std::endl(std::cout); // fully scoped call
return 0;
}// main