I trying to incorporate a simple error logging into my existing app, at the moment it reports errors just using cout so I was hoping to keep a similar interface using the << operator. However I want it to log the line and function the error occurred, but I don't want to have to type __LINE__, __FUNCTION__ every time I need to log. Does anyone know a trick I can use to allow the __LINE__ macro to be used inside another function, reporting the calling line instead? Hope that makes sense.
class myLogClass {
    uint8_t level;                  
public:                 
    bool operator<<( const char * input );          
};
bool myLogClass::operator<<( const char * input ) {
    logItInSQL( input );
    return true;
}
Instead of this every time
myLogClass << "Line No: " << __LINE__
    << " Function: " << __FUNCTION__
    << " Error: " << "This is my error to be logged";
I would like to just be able to do:
myLogClass << "This is my error to be logged";
bool myLogClass::operator<<( const char * input ) {
    logItInSQL( " Line No: __LINE__" );
    logItInSQL( " Function: __FUNCTION__" );
    logItInSQL( " Error: " + input );
    return true;
}
                myLogClass << "Line No: " << __LINE__ ...
With your operator << chaining will not work since it returns a bool. 
bool myLogClass::operator << (const char * input)
It is customary to define stream insertion as follows:
std::ostream& myLogClass::operator << (std::ostream& o, const char * input) {
    // do something
    return o;
}
Do this:
#define log(o, s) o << "Line No: " << __LINE__ << \
                   " Function: " << __FUNCTION__ << \
                   " Error: " << s // note I leave ; out
Additionally, you can wrap the macro in a do-while loop:
#define log(o, s) do { o << "Line No: " << __LINE__ << \
                   " Function: " << __FUNCTION__ << \
                   " Error: " << s; \ 
                  } while(0) // here, I leave ; out
Then you can happily write:
 myLogClass myLogger; // do this
 // use it
log(myLogger, "This is my error to be logged"); // note the ;
                        In ANSI C (which should also work in C++ I assume), you can do that using variadic functions and preprocessor macros. See example below:
#include <stdio.h>
#include <stdarg.h>
#define MAXMSIZE 256
#define MyDebug(...) MyInternalDebug(__FILE__,__FUNCTION__,__LINE__,__VA_ARGS__)
void MyInternalDebug( char *file, char *function, const int line, const char *format, ... )
{
    char message[MAXMSIZE];
    // Variable argument list (VA)
    va_list ap;
    // Initialize VA
    // args : Name of the last named parameter in the function definition.
    // The arguments extracted by subsequent calls to va_arg are those after 'args'.
    va_start(ap, format);
    // Composes a string with the same text that would be printed if 'format' was used on printf,
    // but using the elements in the variable argument list identified by 'ap' instead of
    // additional function arguments and storing the resulting content as a C string in the buffer pointed by 'message'.
    // * The state of arg is likely to be altered by the call.
    vsprintf(message, format, ap);
    // Custom print function
    printf("%s\t%s\t%d\t%s\n",file, function, line, message);
    // Finzalize use of VA
    va_end(ap);
}
int main ()
{  
    MyInternalDebug(__FILE__, __FUNCTION__, __LINE__, "An error occured with message = '%s'", "Stack Overflow");
    MyDebug("Another error occured with code = %d", 666);
    return 0;
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With