tags:

views:

130

answers:

5

I have a logger in a c++ application that uses defines as follows:

#define FINEST(...) Logger::Log(FINEST, _FILE, __LINE, __func, __VA_ARGS_)

However what I would like to do is to be able to switch off these logs since they have a serious performance impact on my system. And, it's not sufficient to simply have my Logger not write to the system log. I really need to get rid of the code produced by the logs.

In order to do this, I changed the define to:

#define FINEST(...)

Which works, but this produces a whole bunch of warning in my code since variables are unused now. So what I would like to have is a sort of NULL FUNCTION that would not actually exist, but would not produce warnings for the unused variables.

So, said another way, I would like it to compile with no warnings (i.e. the compiler thinks that the variables are used for a function) but the function does not actually exist in the application (i.e. produces no performance hit).

Is this possible?

Thanks!

+4  A: 

Have you considered turning off that particular warning of your compiler?
It's probably not a good idea, but if you need a quick and dirty solution...

Cameron
+1 because it _is_ a good idea. Enable the warning during debug build (where that warning isn't triggered wrongly and is useful), then disable for production builds (since we've already gotten the benefit of that warning in the debug build).
Chris Lutz
+3  A: 
template<bool implemented>
void Logger::Log( ... );

template<>
void Logger::Log<true>( ... )
{
  // with implementation
}

template<>
void Logger::Log<false>( ... )
{
  // without implementation
}

// USE:
#define FINEST(...) Logger::Log<true>(FINEST, _FILE, __LINE, __func, __VA_ARGS_)
// or
#define FINEST(...) Logger::Log<false>(FINEST, _FILE, __LINE, __func, __VA_ARGS_)

// EVEN BETTER (w/o macro):
// flag to switch on/off logging
const bool with_log = true; // or =false

// use   
Logger::Log<with_log>( /* place arguments here */ );
Kirill V. Lyadvinsky
Wouldn't this still create code in the program object file and thus impact the performance?
bbazso
This will not create code. At least on most modern compilers with optimization.
Kirill V. Lyadvinsky
+3  A: 

You could define an empty function with unnamed parameters:

void nullFunc(int, int, int, const char*, ...) {
}

Then redefine your macro to call this function:

#define FINEST(...) nullFunc(FINEST, _FILE, __LINE, __func, __VA_ARGS_)
Péter Török
Wouldn't this still create code in the program object file and thus impact the performance?
bbazso
If you make the nullFunc inline no code will be created.
Robert Menteer
@Robert, code for evaluating the arguments will be created though. Imagine `FINEST(generateStackTrace())` would try to create a strack-trace string in release mode.
Johannes Schaub - litb
+3  A: 

On comeau and GCC, the warning disappears if you wrap the variables into a sizeof:

#define FINEST(...) ((void)sizeof(__VA_ARGS__))

To avoid warnings on GCC about that the left or right side of the comma operator has no effect (if it expands to sizeof(a, b) for example), you can introduce a debug-nullify type that has its own comma operator:

struct debug_nullify { };

// doesn't need a definition
template<typename T>
debug_nullify operator,(debug_nullify, T const &);

#define FINEST(...) ((void)sizeof(debug_nullify(), __VA_ARGS__))

The benefit of sizeof is that argument expressions are not evaluated.

Johannes Schaub - litb
You and that comma operator.
GMan
Argh! I was going to post this! Oh wait, I already did: http://stackoverflow.com/questions/2230768/what-is-the-optimization-with-highest-roi-you-ever-did-to-your-code/2230868#2230868Blargh.
MSN
@GMan, lol i couldn't help but post a silly work-around xD See @DavidX's answer for teh real way to do it xD
Johannes Schaub - litb
+2  A: 

I would reccomend removing the declarations in release too:

int somefunc(int foo, int bar, void* baz)
    {
    DEBUGVAR(Logger,log);
    int othervar;
    /* stuff */
    MAYBELOG(log,"something happened: %i",othervar);
    /* other stuff */
    return 0;
    }

in define:

#if DEBUGLEVEL>0
#define DEBUGVAR(type,...) type __VA_ARGS__
#define MAYBELOG(logger,str,...) logstuff(logger,__FLIE__,__LINE__,str,__VA_ARG__)
#else
#define DEBUGVAR(type,...)
#define MAYBELOG(logger,str,...)
#endif
David X
I like this idea the most. I would personally go with this solution if i were him.
Johannes Schaub - litb