How does “std::cout << std::endl;” compile?

后端 未结 4 2165
北荒
北荒 2020-12-10 12:36

Most IO stream manipulators are regular functions with the following signature:

std::ios_base& func( std::ios_base& str );

However

相关标签:
4条回答
  • 2020-12-10 13:05

    You need to put << before the endl. It is a member of ofstream:

    namespace std {
    template <class charT, class traits = char_traits<charT> >
    class basic_ostream {
    public:
        basic_ostream<charT,traits>& operator<<(
          basic_ostream<charT,traits>& (*pf)(basic_ostream<charT,traits>&));
        // ...
    };
    
    }
    

    endl works like a "/n" to skip the line, so you need a cout line to skip

    0 讨论(0)
  • 2020-12-10 13:13

    Given a statement expression of the form

     std::cout << std::endl;
    

    The compiler has information about the type of std::cout - which is a specialisation of the templated std::basic_ostream which looks something like (omitting the containing namespace std).

    template <class charT, class traits = char_traits<charT> >
        class basic_ostream
    {
        public:
            basic_ostream<charT,traits>& operator<<(
                basic_ostream<charT,traits>& (*pf)(basic_ostream<charT,traits>&));
    };
    

    Since the compiler has information about the type of std::cout it knows what charT and traits are to specialise the preceeding template.

    The above causes std::endl in the expression std::cout << std::endl to match to the specific std::basic_ostream<charT, traits>& endl( std::basic_ostream<charT, traits>&).

    The reason type deduction doesn't work in

     auto myendl = std::endl;
    

    is because std::endl is a templated function, and this declaration provides no information to specialise that template (i.e. picking what charT or traits are). If it can't specialise the templated std::endl, it can't infer that function's return type, so the type deduction fails.

    0 讨论(0)
  • 2020-12-10 13:20

    The operator<< in question is a member of std::basic_ostream:

    namespace std {
        template <class charT, class traits = char_traits<charT> >
        class basic_ostream {
        public:
            basic_ostream<charT,traits>& operator<<(
              basic_ostream<charT,traits>& (*pf)(basic_ostream<charT,traits>&));
            // ...
        };
    }
    

    Since the call is to std::cout << std::endl, or equivalently std::cout.operator<<(std::endl), we already know the exact instantiation of basic_ostream: std::basic_ostream<char, std::char_traits<char>>, aka std::ostream. So the member function of cout looks like

    std::ostream& operator<<(std::basic_ostream<char, std::char_traits<char>>& (*pf)
        (std::basic_ostream<char, std::char_traits<char>>&));
    

    This member function is not a function template, just an ordinary member function. So the question remaining, is can it be called with the name std::endl as an argument? Yes, initializing the function argument is equivalent to a variable initialization, as though we had written

    std::basic_ostream<char, std::char_traits<char>>& (*pf)
        (std::basic_ostream<char, std::char_traits<char>>&) = std::endl;
    
    0 讨论(0)
  • 2020-12-10 13:24

    Because basic_ostream has a templated overload of operator<< that expects just such a function pointer:

    basic_ostream<charT, traits>& operator<<(basic_ios<charT, traits>& (*pf)(basic_ios<charT, traits>&));
    
    0 讨论(0)
提交回复
热议问题