I´m currently learning C and I decided to try to write my own "log tool". My goal is, that I can write just something like this:
logger<<"log message";
I have this problem - when I wrote operator << overloading function, the IDE compiler warned me, that it is infinite recursion.
Here is the code of operator overloading:
Logger &operator<<(Logger &logger, char *message)
{
logger << message << "Log message";
return logger;
}
And function is in class declared as friend:
friend Logger &operator<<(Logger &logger, char *message);
Why is this code infinite recursion? Maybe I just can´t see some trivial mistake...
Thank you for your answers.
CodePudding user response:
Logger &operator<<(Logger &logger, char *message)
This declares an operator<<
overload. It takes a left-hand side parameter that's a Logger &
, and a right-hand side parameter that's a char *
, that's what this means in C .
logger << message
And this invokes the <<
operator. Amongst all the defined operator overloads for <<
, there is one operator overload that will work here: this particular operator overload takes a left-hand side parameter that's a Logger &
-- and this logger
object meets this criteria smashingly well -- and a right-hand side parameter that's a char *
-- that's equally met well by the message
object.
In other words, this calls the same operator<<
overload, hence the infinite recursion.
CodePudding user response:
In order to invoke your overloaded operator<<
from anywhere, you need a Logger
object on the left side and a char*
pointer (BTW, it should be const char*
instead) on the right side.
Inside your overloaded operator<<
, this statement:
logger << message
is trying to invoke an operator<<
with a Logger
object on the left side and a char*
pointer on the right side.
So, what do you think that is going to invoke? That's right, ITSELF! Over and over, endlessly, forever. That is what the compiler is warning you about.
You need to replace logger
in that statement with whatever std::istream
(or other object) that the Logger
class wants to write to. Not the Logger
itself.
For example, let's say your Logger
class has a data member named m_file
. Your overloaded operator<<
could then look like this:
Logger& operator<<(Logger &logger, const char *message)
{
logger.m_file << message << "Log message";
return logger;
}