0

I want to write a mini logger in c++ and I want to implement something like this:

logger(log_level)<<"Aditional message"<<maybe an integer<<maybe a string<<etc;

and this needs to be able to write something like this: "date app_name user error_level Aditional_message" in a file. I know that i need to overload the operators () and <<. I Think that logger() should return a reference to the object itself, but i don't know how to overload << in order to achive what i want. Should i return a string and in the definition to do something like appendig? I hope I wasn't too vague.

  • 3
    Seems to me that your `<<` overload should return `*this`, so that the next `<<` operator gets overloaded the same way. And have `logger()` return a temporary that has the overloaded `<<` operator implemented, and a destructor that finalizes the complete message and logs it. Then, this syntax should work as expected. – Sam Varshavchik Apr 05 '20 at 18:43
  • 1
    Do you really need that syntax? `logger(log_level, "Aditional message", maybe an integer, maybe a string, etc);` would be much simpler. – walnut Apr 05 '20 at 18:44
  • You don't need to overload `operator()`. `logger()` can be a function that returns an object. Or a constructor. But yes, either way, you need to overload `operator<<`. Have it return a reference to an `ostream` that the logger owns, or return a reference to the logger itself. That is what allows multiple `operator<<` calls to be chained. – Remy Lebeau Apr 05 '20 at 18:44
  • @walnut `<<` hell seems like heaven until you have suffered it :D – Acorn Apr 05 '20 at 18:44
  • 1
    Does this answer your question? [Overloading operator << - C++](https://stackoverflow.com/questions/601219/overloading-operator-c/601283) – 273K Apr 05 '20 at 18:46
  • 1
    One downside to this approach is if the log_level is below the threshold, then the output will still do all the work, but the work is busy work. Only important if you're counting cycles. – Eljay Apr 05 '20 at 18:48
  • @Acorn Actually I just realized that there is one benefit to it since C++17: The order of evaluation is guaranteed, while that is not the case for the function call syntax. – walnut Apr 05 '20 at 18:50
  • @walnut I would consider that a downgrade: most of the times you don't care about the order, so I prefer the compiler can reorder things. If I really need to guarantee some specific order, I prefer to perform the computation before (outside) the call! – Acorn Apr 05 '20 at 18:52

1 Answers1

0

This is actually interesting I've never done anything like this, try this, it works on GCC very good!

#include <iostream>
#include <sstream>
#include <fstream>

#define LOGGER(streamText) {   \
    std::ostringstream buffer; \
    buffer << streamText;      \
    std::ofstream logs; \
    logs.open("logs.txt",std::ios::app); \
    logs << buffer.str() << std::endl; \
}
int main()
{
    LOGGER("Error level" << 1 << "Deploy the semicolons" << 3.1);
    return 0;
}
aliberro
  • 530
  • 2
  • 9
  • A macro works, yes, but OP seems to want to avoid that. – Acorn Apr 05 '20 at 19:05
  • Macros are best avoided in C++. You cannot use this solution more than once in a scope (so you cannot e.g. log two lines in one function) and opening a file every time a log is needed is sub-optimal. – Yksisarvinen Apr 05 '20 at 19:22