2

I want to make a behavior like std::cout has:

int a = 10, b = 15, c = 7;
MyBaseClass << "a = " << a << ", b = " << b << std::endl;

I try to implement some things which I've just read but it doesn't work for me. I want to implement operator in one class which I call MyBaseClass. I tried this:

class MyBaseClass {
    private:
        std::ostream someOut;
    public:
        // My first try:
        std::ostream &operator<< ( std::ostream &out, const std::string &message ) {
        }

        // The second try:
        std::ostream &operator<< ( const std::string &message ) {
            someOut << message << std::endl;
            return someOut;
        }

        void writeMyOut() { 
            std::cout << someOut.str() 
        };
};

When I compile this I get: "Call to implicity-deleted default constructor of 'MyBaseClass'" - what do I need to do to fix it?

OS X, Xcode, clang compiler, all is up-to-date.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
JavaRunner
  • 2,455
  • 5
  • 38
  • 52
  • Possible duplicate [C++ Beginner - 'friend' functions and << operator overloading: What is the proper way to overload an operator for a class?](http://stackoverflow.com/questions/2828280/c-beginner-friend-functions-and-operator-overloading-what-is-the-prope) – Joel Apr 12 '16 at 04:56
  • I think your second try should work, more or less. The compile error is probably because `MyBaseClass` has no constructors, but you need one to initialize the`someOut` member. (I'm not 100% sure that's the problem, but if you provide a constructor for `MyBaseClass`, I think you'll get a little further. Specifically, I think you'll get far enough to try to write on the uninitialized `std::ostream` called `someOut`.) – Dave M. Apr 12 '16 at 04:58
  • @DaveM. - if I add an empty constructor I get: `Field of type 'std::ostream' (aka 'basic_ostream') has protected default constructor` – JavaRunner Apr 12 '16 at 05:01
  • @Joel: this question is not about creating an `operator<<` to stream a user-defined type (per your duplicate candidate), but about making a type to which other types can be streamed. It's probably a duplicate too, but harder to find. – Tony Delroy Apr 12 '16 at 05:01
  • The problem is, you're not initializing the `std::ostream`. I'm not sure you _can_ create a plain `ostream` -- you generally either create an `ofstream` or an `ostringstream` (maybe now called an `ostrstream`? I forget.) Try replacing `std::ostream` with `std::ostringstream`. – Dave M. Apr 12 '16 at 05:06
  • @DaveM.: `ostringstream` is the replacement for the `ostrstream` of yesteryear... – Tony Delroy Apr 12 '16 at 05:08

1 Answers1

3

You're trying to output a variety of value types into the MyBaseClass object, so need to support the same set. I've also changed someOut to be a std::ostringstream, which is capable of accumulating the output. You might equally have wanted it to be a std::ostream& to a caller-provided stream passed to the constructor....

class MyBaseClass {
    private:
        std::ostringstream someOut;
    public:
        ...other functions...
        // The second try:
        template <typename T>
        MyBaseClass& operator<< ( const T& x ) {
            someOut << x;
            return *this;
        }

        void writeMyOut() const { 
            std::cout << someOut.str() 
        };
};
Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • In this case I get: `Call to implicitly-deleted default constructor of 'MyBaseClass'` – JavaRunner Apr 12 '16 at 05:03
  • @JavaRunner: have you provided any `MyBaseClass` constructors yourself (perhaps at DaveM's prompting)? If so, remove them. With `std::ostream& someOut;` you'd need `MyBaseClass(std::ostream& os) : someOut(os) { }`, but you don't need to specify any constructor for `std::ostringstream`. – Tony Delroy Apr 12 '16 at 05:04
  • Thanks, your solution works like a charm! It was my fault. – JavaRunner Apr 12 '16 at 05:07
  • 1
    @JavaRunner: sure, no worries. Hope you enjoy your C++ coding. Cheers. – Tony Delroy Apr 12 '16 at 05:09