-2

There have been a couple posts on this subject, but I think this is one of the simplest examples, and hopefully it will clarify some things about cout and initialization.

So this works:

class A {
  public:
    std::ostream& operator<< (std::ostream& os) {
      return os;  
    }
};

class B {
    std::ostream& operator<< (std::ostream& os) {
      A a(); //        <-- LOOK
      std::cout << a;
      return os;  
    }
};

But if I simply A a() to A a:

class A {
  public:
    std::ostream& operator<< (std::ostream& os) {
      return os;  
    }
};

class B {
    std::ostream& operator<< (std::ostream& os) {
      A a; //        <-- LOOK
      std::cout << a;
      return os;  
    }
};

It throws:

nvcc main.cpp util.cpp -o main -lcublas -std=c++11
In file included from main.cpp:9:0:
cout-test.hpp: In member function ‘std::ostream& B::operator<<(std::ostream&)’:
cout-test.hpp:21:20: error: cannot bind ‘std::ostream {aka std::basic_ostream<char>}’ lvalue to ‘std::basic_ostream<char>&&’
       std::cout << a;
                    ^
In file included from /usr/include/c++/4.8/iostream:39:0,
                 from main.cpp:5:
/usr/include/c++/4.8/ostream:602:5: error:   initializing argument 1 of ‘std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = A]’
     operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
     ^
make: *** [main] Error 1

I get the same error if I make A a a class member:

class B {
    A a; //        <-- LOOK
    std::ostream& operator<< (std::ostream& os) {
      std::cout << a;
      return os;  
    }
};

What gives?

ethanabrooks
  • 747
  • 8
  • 19
  • `std::cout << a` does ***not*** invoke the `operator<<` member function. And the only reason the first code compiles is because it's [a most vexing parse](https://en.wikipedia.org/wiki/Most_vexing_parse). – Sam Varshavchik Nov 20 '16 at 02:43
  • Great to know! Can you please explain that a little more? – ethanabrooks Nov 20 '16 at 03:07

1 Answers1

1

First Case

  A a();

does not construct an object. It declares a function. This parsing problem is known as The Most Vexing Parse.

  A a();
  std::cout << a;

works because a is converted to a bool in this case. See Why does pointer to int convert to void* but pointer to function convert to bool? why that works.

Second Case

  A a;
  std::cout << a;

does not work because of the way you have defined the operator<< function. You'll have to use

  A a;
  a << std::cout;

The operator<< function needs to be a non-member function in order to use:

  A a;
  std::cout << a;

See my answer to another SO post to understand why.

Community
  • 1
  • 1
R Sahu
  • 204,454
  • 14
  • 159
  • 270