1

I am writing some macro (yes I know it's evil, but it helps me make more optimized code) that looks like this:

#define HUGGLE_DEBUG(debug, verbosity) if (Huggle::Configuration::HuggleConfiguration->Verbosity >= verbosity) \
                                          Huggle::Syslog::HuggleLogs->DebugLog(debug, verbosity)

function DebugLog(QString, unsigned int Verbosity = 1) has optional parameter Verbosity and I would like to make it optional in macro as well, so that I can call

HUGGLE_DEBUG("some debug text");

as well as:

HUGGLE_DEBUG("more verbose text", 10);

Is it somehow possible? Note: I am using the second variable in macro, but if I didn't have it, I could just substitute it to 1

My idea is to make a variadic macro from this, which would work like this:

#define HUGGLE_DEBUG(debug, ...)    Syslog::HuggleLogs->DebugLog(debug, ##__VA_ARGS__)

which would work but it would kind of not use the optimization I did in first one

4
  • 2
    Have you profiled and verified that an inline functions really turns out worse than a macro? Commented Jun 18, 2014 at 12:49
  • The problem here is that I often use a complicated construction as a parameter, like DebugLog("some text " + fc_that_returns_text() + " bla") which itself calls lot of text processing functions. I want to avoid having to call it, unless I am really in debugging mode (that is why I want to wrap the call of function in if block of code), if the function was just inline, the parameter would have to be constructed anyway, then it just wouldn't be used Commented Jun 18, 2014 at 12:53
  • No, if the function is inlined, it is replaced in place. So the string argument would only be evaluated when the if passes. That's the principle of inlining. Commented Jun 18, 2014 at 12:57
  • Of course the inline function HUGGLE_DEBUG would have to be defined in a header file, but that just means that header file would need access to the declaration of Verbosity and DebugLog. It doesn't need their definition. Commented Jun 18, 2014 at 13:03

2 Answers 2

2

Seeing as you're using a macro already, you probably won't mind a very hacky solution:

#define HUGGLE_DEBUG(...) \
  if (Huggle::Configuration::HuggleConfiguration->Verbosity >= ((int)(bool)__VA_ARGS__)) \
    Huggle::Syslog::HuggleLogs->DebugLog(__VA_ARGS__)

When called with one argument:

HUGGLE_DEBUG("abc")

// expands to

if (Huggle::Configuration::HuggleConfiguration->Verbosity >= ((int)(bool)"abc"))
    Huggle::Syslog::HuggleLogs->DebugLog("abc")

(bool)"abc" is true, so (int)(bool)"abc" is 1.

When called with two arguments:

HUGGLE_DEBUG("abc", 10)

// expands to

if (Huggle::Configuration::HuggleConfiguration->Verbosity >= ((int)(bool)"abc", 10))
    Huggle::Syslog::HuggleLogs->DebugLog("abc", 10)

(int)(bool)"abc", 10 uses the comma operator, so it evaluates to 10.

But please please, consider using an inline function instead. There's no need to use a macro for this.

Sign up to request clarification or add additional context in comments.

1 Comment

This solution kills the performance tweak as it needs to evaluate the argument anyway (during if - the first argument, which isn't a text but instance of QString may be complex, include concatenation through overload of + operator, or some other functions that needs to be called). But the last sentence is correct. Inlined and works.
1

There is also a solution with Boost.Preprocessor:

#define HUGGLE_DEBUG_1( debug ) HUGGLE_DEBUG_2( debug, 1 )
#define HUGGLE_DEBUG_2( debug, verbosity ) \
if( Huggle::Configuration::HuggleConfiguration->Verbosity >= verbosity) \
    Huggle::Syslog::HuggleLogs->DebugLog(debug, verbosity)

#define HUGGLE_DEBUG( ... ) BOOST_PP_OVERLOAD(HUGGLE_DEBUG_,__VA_ARGS__) (__VA_ARGS__)

It is more flexible than the approach using the comma operator, since you can use any default argument, not just 1.

Still: Use inline functions (or Lambdas).

1 Comment

+1 for a less hacky solution. But note that mine could be extended to other default values as well: 4 & ~ !__VA_ARGS__, for example.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.