Print-based debugging #include &lt;iostream&gt;

const bool DEBUG = false;

template &lt;typename ... Args&gt;
void debug(Args ... args);

template &lt;typename ... Args&gt;
void _debug(Args ... args) {
    std::cout &lt;&lt; "[" &lt;&lt; __FILE__ &lt;&lt; ":" &lt;&lt; __LINE__ &lt;&lt; "] ";
    (std::cout &lt;&lt; ... &lt;&lt; args) &lt;&lt; std::endl;
}

#define debug(args...) if (DEBUG) _debug(args);


Suppose you are running ACM or you are somewhere without a well-crafted development environment. You have written some code and wondering what is going wrong.

Goal here is to find out what cause the problem as quickly as possible by placing tracing prints and turn them off all together by preventing code generation for them. So you can  submit your code with DEBUG = false and it will not cause any performance issues done by calling debug(...).
Although it's a short function/macro, there are a number of problems here:

__FILE__ and __LINE__ are expanded in the function definition, rather than at the call site.  We need an interface that passes those in, so that the macro is
  #define debug(args...) if (DEBUG) _debug(__FILE__, __LINE__, args);


That's a non-standard variadic macro expansion.  The standard way is to write the parameter as ... and expand it using __VA_ARGS__.

Identifiers in global scope beginning with underscore are reserved for the implementation.  Use a namespace instead (e.g. debugging::debug).

Debug information should go to std::clog, not std::cout.

The macro doesn't play nicely in if/else statements - use the do...while(0) idiom to make it statement-like.

Conventional style is to use all-caps for macros (to indicate their dangers) and nothing else.  We have this exactly backwards here, with debug and DEBUG.



Improved version
#include &lt;iostream&gt;

namespace debugging
{
#ifdef ENABLE_DEBUG
    constexpr bool debug = true;
#else
    constexpr bool debug = false;
#endif

    template &lt;typename... Args&gt;
    void print(const char* file, int line, Args... args) {
        (std::clog &lt;&lt; &quot;[&quot; &lt;&lt; file &lt;&lt; &quot;:&quot; &lt;&lt; line &lt;&lt; &quot;] &quot;
                  &lt;&lt; ... &lt;&lt; args) &lt;&lt; std::endl;
    }
}

#define DEBUG(...)                                              \
    do {                                                        \
        if (debugging::debug)                                   \
            debugging::print(__FILE__, __LINE__, __VA_ARGS__);  \
    } while (0)

And a quick test (that demonstrates that the arguments are evaluated only when we're debugging):
int main()
{
    DEBUG(&quot;Started main&quot;);
    int status = 1;
    DEBUG(&quot;Leaving main, status=&quot;, status=0);
    return status;
}


Addendum
We don't need the debug constant - just change the definition of the macro according to whether or not we're debugging:
#ifndef ENABLE_DEBUG
#define DEBUG(...)  ((void)0)
#else
#include &lt;iostream&gt;

namespace debugging
{
    template&lt;typename... Args&gt;
    void print(const char* file, int line, Args... args) {
        (std::clog &lt;&lt; &quot;[&quot; &lt;&lt; file &lt;&lt; &quot;:&quot; &lt;&lt; line &lt;&lt; &quot;] &quot;
                  &lt;&lt; ... &lt;&lt; args) &lt;&lt; std::endl;
    }
}

#define DEBUG(...)  debugging::print(__FILE__, __LINE__, __VA_ARGS__)
#endif