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

后端 未结 3 1200
孤街浪徒
孤街浪徒 2020-12-23 23:59

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

#include 

int main() {
           


        
相关标签:
3条回答
  • 2020-12-24 00:43

    The compiler sees that the arguments to << are an std::ostream object and a string, and so is able to locate the proper operator<< definition based on this.

    You can sort of think of the argument types of an operator (or really, any function) as part of its name.

    0 讨论(0)
  • 2020-12-24 00:54

    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 :)

    0 讨论(0)
  • 2020-12-24 00:59

    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
        }
    }
    
    0 讨论(0)
提交回复
热议问题