문제

This is related to the difference-between-cout-x-and-cout-operator-x question, but still a little different...

#include <iostream>

int main(){
    std::cout << "hello" << std::endl;

    std::cout.operator<<("hello2");
    std::cout.operator<<(std::endl);

    operator<<(std::cout, "hello3");
//    operator<<(std::cout, std::endl);

    return 0;
}

Q1: Why does std::cout.operator<<("hello2"); work?

From other answers on SO I would expect the compiler to complain since operator<< is meant to be a free function and not a member of cout. On my system, however, it prints "0x10d54df31". And, stranger yet, the following line correctly correctly executes std::endl.

Q2: Why does operator<<(std::cout, std::endl); not work?

I know that std::endl is a function, but it seems strange (to me) that the hello3 output works whilst the `std::endl' doesn't. Instead the compiler throws an error:

main.cpp:10:4: error: no matching function for call to 'operator<<'
    operator<<(std::cout, std::endl);

Q3: How can the first std::cout << "hello1" << std::endl; be written in operator<<(...) form?

If the first two questions have been answered, then this has probably already covered. It's the point of this learning exercise, so seems sensible to ask it explicitly.

도움이 되었습니까?

해결책

Operators can be implemented in different ways, in particular an operator<< for which the left hand side is your type can be implemented as either a free function or as a member function of that left hand side type.

While you must implement ostream& operator<<(ostream&, MyType const&) as a free function (since MyType is not the left hand side), the library implementation can choose* to implement operator<< for some fundamental types insde the std::ostream type (which is really a particular instantiation of a template, I am trying to ignore the details).

Edit: After checking with the standard this is incorrect:

This is what you are noticing in the code, the overload that takes a const char* is implemented as a member of ostream (basic_ostream<char,char_traits<char>).

The overloads taking manipulators are implemented as member functions (Q2), and there is an implicit conversion from const char* to const void* that will be picked if you use the syntax for explicitly calling a member operator (Q1). For Q3, the answer would be:

operator<<(std::cout, "Hello").operator<<(std::endl);

* The implementation is actually not free to choose, since the standard mandates the signatures.

다른 팁

Some overloads of operator<< are class members, others are not.

In C++03 this created some baffling call scenarios since a reference to non-const (argument of the not-member) can't be bound to an rvalue, but in C++11 at least one such has been fixed by introducing an rvalue reference argument overload.

So, which calls compile or not depends more in general also on the C++ standards version, C++03 or C++11.

There is a bunch of member output operators defined in std::ostream. In retrospect that was probably an error but when IOStreams were first created I think it was actually necessary. These member operators include the overloads taking function pointers which means you'll need to use member notation for those. The operators using C-strings are non-member overloads, i.e., you need to use the non-member function call notation to get the C-string overload. When you call the member operator with a char const* the char const* will be converted to void const* for which there is a member output operator.

Your questions can be broken down to member functions an non-member functions.

Having 13.5.2 Binary operators

A binary operator shall be implemented either by a non-static member function (9.3) with one parameter or by a non-member function with two parameters. Thus, for any binary operator @, x@y can be interpreted as either x.operator@(y) or operator@(x,y). If both forms of the operator function have been declared, the rules in 13.3.1.2 determine which, if any, interpretation is used.

Omitting a quote of 13.3.1.2 the member function (operator) is preferred.

The line 'std::cout << "hello" << std::endl;' involves non member functions. Each 'std::cout.operator' is an explicit member function call.

  • Q1 is the member operator<<(const void*)
  • Q2 there is no member taking a function
  • Q3 It is not possible
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top