Łukasz Przeniosło Łukasz Przeniosło - 1 month ago 4
C++ Question

c++ operator<< as parameter

Normally for overloading operator<< for a class in c++ I would do something like:

template <typename T>
void operator<< (const T &t)
{
ostringstream stream;
stream << t;
// more code
}


I was wondering however either it would be possible to make the operator<< to be one of the parameters. One could create a method with
va_list
in order to format a string and pass additional parameters, for example:

void CBcLogger::print(MLL::ELogLevel lvl, const char* text, ...)


As you see in the above method I can pass the text to be formatted, as well as
lvl
parameter. If I wanted to use
operator<<
, would I be able to somehow squize more parameters than just the operator? Something like

void multiParamFunc(const unsigned int logLevel, "operator<< here")


I know this is not the right syntax and all but I am just trying to make a point.

I would appreciate all help regarding this case.
Also, I ask this in regard to pure c++ but in the end I would use it with QT. Maybe this framework gives some more functionalities?

Edit: I am making a logger framework. I need a function that would allow one to add a log line, which is described with its log lever (debug, info, error etc. Its an enum) and a "stream" that can be formatted with operator<< or va_args like in printf.

For example, the
print
call would look like this:

print(MLL::ERROR, "Some text to format %u %i %f", 1, -1, 3.14f);


As you see I can pass the log level parameter to this function. I am wondering how can I achieve simmilar functionality with operator<<.

Answer

Not sure if this exactly is what you want to do, but why not just have a simple class that contains a reference to the appropriate ostream?

class Message : public std::ostream{
  enum LogLevel { DEBUG, INFO, WARNING, ERROR };
  std::ostream* os;
public:
  static LogLevel threshold = DEBUG;
  Message(LogLevel level) : os(0){
    if(level > threshold){
      os = level > INFO ? &std::cerr : &std::cout;
    }
  }

  template<class T> std::ostream& operator<< (const T& t){ 
    return os ? (*os)<<t : this;
  }
};

Message(Message::DEBUG)<<"This won't be printed.\n";
Message(Message::INFO) <<"This will go to stdout.\n";
Message(Message::ERROR)<<"This will go to stderr.\n";

I don't think this will work as written but gives the basic idea. To be a little more advanced, you can have the Message class own an ostringstream, which you can then also clone to a logfile in addition to cout/cerr, similar to this

Comments