Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why I have to write std::cout and not also std::<<

Tags:

c++

Why do I have to write std::cout and not also std::<< in a line of code like this:

#include <iostream>  int main() {     std::cout << "Hello, world!";     return 0; } 

cout comes from std library, and isn't << usually used to do bits shifting? So, why don't I have to write the scope operator :: also before <<, since it is used also with another meaning? How the compiler knows that after std::cout, << means another thing?

like image 649
Francesco Bonizzi Avatar asked Oct 01 '13 17:10

Francesco Bonizzi


People also ask

Why do I need std :: cout?

Difference between cout and std::cout in C++ The cout is a predefined object of ostream class, and it is used to print the data on the standard output device. Generally, when we write a program in Linux operating system for G++ compiler, it needs “std” namespace in the program.

Why do we need std :: in C++?

The string and vector which we want to use are in the C++ standard library, so they belong to the std namespace. This is why you need to add std:: to them. It is the same reason to use std:: for cout and cin .

Can I have a C++ program without using namespace std?

It is not necessary to write namespaced, simply use scope resolution (::) every time uses the members of std. For example, std::cout, std::cin, std::endl etc.

How can I print without using namespace std?

You do not need using namespace std , and you shouldn't use it. Use fully qualified names std::cout and std::endl , or, in a small scope, using std::cout; using std::endl; As for the other questions, std::cout is not a function.


2 Answers

First, the compiler will look at the types to the left and right of <<. std::cout is of type std::ostream, the string literal is of type array of 15 const char. As the left is of class type, it will search for a function named operator<<. The question is, where will it look?

The lookup for this name operator<< is a so-called unqualified lookup, because the function name isn't qualified like std::operator<<. Unqualified lookup for function names invokes argument-dependent lookup. The argument-dependent lookup will search in the classes and namespaces associated with the argument types.

When you include <iostream>, a free function of the signature

template<typename traits> std::basic_ostream<char, traits>& operator<<(std::basic_ostream<char, traits>&,                                              const char*); 

has been declared in namespace std. This namespace is associated with the type of std::cout, therefore this function will be found.

std::ostream is just a typedef for std::basic_ostream<char, std::char_traits<char>>, and the array of 15 const char can be converted implicitly to a char const* (pointing to the first element of the array). Therefore, this function can be called with the two argument types.

There are other overloads of operator<<, but the function I mentioned above is the best match for the argument types and the one selected in this case.


A simple example of argument-dependent lookup:

namespace my_namespace {     struct X {};      void find_me(X) {} }  int main() {     my_namespace::X x;     find_me(x);       // finds my_namespace::find_me because of the argument type } 

N.B. As this function is a operator, the actual lookup is a bit more complex. It is looked up via qualified lookup in the scope of the first argument (if that's of class type), i.e. as a member function. Additionally, unqualified lookup is performed, but ignoring all member functions. The result is slightly different, because unqualified lookup is actually like a two-step procedure, where argument-dependent lookup is the second step. If the first step finds a member function, the second step is not performed, i.e. argument-dependent lookup is not used.

Compare:

namespace my_namespace {     struct X     {         void find_me(X, int) {}         void search();     };     void find_me(X, double) {}      void X::search() {         find_me(*this, 2.5); // only finds X::find_me(int)         // pure unqualified lookup (1st step) finds the member function         // argument-dependent lookup is not performed     } } 

to:

namespace my_namespace {     struct X     {         void operator<<(int) {}         void search();     };     void operator<<(X, double) {}      void X::search() {         *this << 2.5; // find both because both steps are always performed         // and overload resolution selects the free function     } } 
like image 166
dyp Avatar answered Sep 22 '22 06:09

dyp


In std::cout << "Hello, world!"; //calls std:::operator <<

This is achieved with Argument-dependent name lookup (ADL, aka Koenig Lookup)

Although we have only one std qualifier but there are two things that comes up from std namespace

  • cout
  • <<

Without ADL, (Koenig Lookup)

std::cout std:: << "Hello World" ;//this won't compile

In order to compile it, we need to use it more uglier form

std::operator<<(std::cout, "Hello, world!");

So to avoid such ugly syntax we must appreciate Koenig Lookup :)

like image 34
P0W Avatar answered Sep 20 '22 06:09

P0W