c++coutostream

C++ function call in cout leads to "Reference to non-static member function must be called"


I wanted to print some properties directly to cout. Luckily I found a solution for static calls like this:

// somewhere:
ostream & Foo(ostream &ostr){
    ostr << "Foo";
    return ostr;
}

and another static call where it can be called directly like that:

// somoewhere else:
void doSomething(){
    cout << 123 << Foo << endl;
}

This works fine and prints simply "123Foo". But I want to use this for an object I have, so I could print its properties. In my class A I have a property b of the class B. There the function is implemented similar to the static one before:

ostream & Foo(ostream &ostr) {
    ostr << "my foo is 123";
    return ostr;
}

but it doesn't compile. I also tried to specify the namespace like

ostream & B::Foo(ostream &ostr) { ... }

and assumed I could just call the object's function like this:

cout << 123 << b->Foo << endl;

but it always tells me there is an error: "Reference to non-static member function must be called".

I just can't get this done. What am I doing wrong? Is this even possible?

NOTE: I don't want to overload the << operator or anything. I don't want a "toString()" method or anything similar but would like to understand why this instance method can not be called like anywhere else. As a Java developer I would have guessed something like "My object " + b.foo() would be possible. But it seems, it is not.


Solution

  • The problem is that your standalone foo is a function, whereas b->foo is, according to C++, not one. Namely, the latter binds its this argument, so it requires some extra data on top of just the function's behavior. You can make it a valid std::function with an explicit lambda.

    cout << 123 << [&b_object](ostream& out) { return b_object->foo(out); } << endl;
    

    and if that's your only intended use case for this function, then you can return it from B::Foo directly.

    // Be careful with lifetimes! The return value cannot
    // outlive `this`!
    std::function<ostream&(ostream&)> B::foo() {
      return [&this](ostream& out) { out << "my foo is " << my_foo; return out; };
    }
    

    Then you can write

    cout << 123 << b_object->foo() << endl;
    

    But, as indicated in the comments, it's much more common to use a specialized datatype for this. If the property you're trying to print is cheap, then just return it or a reference to it from foo() and you're done. If not, or if you want some complicated custom printing operation to happen, I recommend writing your own custom class and encapsulating this custom print behavior.

    class ViewOfObjectB {
    private:
      B& owner;
    public:
      ViewOfObjectB(B& owner) : owner(owner) {}
      friend ostream& operator<<(ostream&, const ViewOfObjectB&);
    };
    
    ostream& operator<<(ostream& out, ViewOfObjectB& obj) {
      // Whatever you want to print goes here ...
      return out;
    }
    
    class B {
    public:
      ViewOfObjectB foo() {
        return ViewOfObjectB(&this);
      }
    };
    

    Same idea as using a lambda, but since there's a ton of hidden complexity, we make that complexity explicit with a named view class that we can document independently as our code grows and becomes more complicated. You still call it using

    cout << 123 << b_object->foo() << endl;
    

    All of these calls are static (in the sense of "no vtable involved", not in the sense of the static keyword), so a clever optimizer should be able to inline it all for you.