3

I am on implementing a class, and I'd like to pass some parameters to the instance using <<.

For example,

terminal term;
term << "Hello World!" << '\n';

The code goes below,

class terminal {
    template <typename T>
    terminal& operator << (T& t) {
        std::cout << t;
        return *this;
    }
};

Basically, I'd like to be a stream instead of being the part of stream. (not cout << term;)

(Sorry for that I forgot to specify my question) The question is, it worked well with strings, but it compiled failed if there is a number (like int, char, etc).

If we use the example above, the compiler will complain that

Invalid operands to binary expression ('terminal' and 'int')

0xBBC
  • 105
  • 2
  • 8

2 Answers2

2

I would change to the following, in order for sequencing of operator<< (e.g., term << "hello" << std::endl; ) to work:

namespace foo {

class terminal {    
  std::ostream &strm;
public:
  terminal(std::ostream &strm_) : strm(strm_) {}
  terminal() : strm(std::cout) {}

  template <typename T>
  friend std::ostream& operator<<(terminal &term, T const &t);
};

template <typename T>
std::ostream& operator<<(terminal &term, T const &t) {
  term.strm << t;
  return term.strm;
}

}

Live Demo

101010
  • 41,839
  • 11
  • 94
  • 168
1

The problem is that your operator << takes its argument by reference to non-const, which means it can only bind to lvalues. So things like non-string literals are out. If you do not need to modify the argument, take it by const & instead. The language has a special rule which allows lvalue references to const to bind to rvalues as well.

terminal& operator << (const T& t) {
    std::cout << t;
    return *this;
}

If you do need to modify the argument, use a different approach than <<. A stream-like interface which would modify the streamed arguments during << would be extremely counterintuitive and a maintenance nightmare.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455