UNUSED() with teeth in C++11 debug builds When you turn up the compiler warnings with -Wunused-variable, one tends to then employ an UNUSED() macro, to say something is intentionally not used at this time.

But that's not very binding, since it's generally just a void cast (or near-equivalent).  Hence if you get the warning, add an UNUSED(), and some time later actually do use the variable...it's misleading to to the reader of the code.

I got the odd idea of making C++11 give this some level of "enforcement", by seeing if it got in a POD lvalue it could trash it.  Obviously won't work for everything (unused constants, etc.)  But I kind of fiddled with it until it had the effect I wanted--while I can't say exactly why every variation I tried didn't work.

You could break it out in various ways to do something special for std::is_pointer&lt;&gt; or other types, or even have some kind of "trashme()" method detection for non-POD values.  But here's the core of the idea:

#if !defined(NDEBUG)

template&lt;
    typename T,
    typename TRR = typename std::remove_reference&lt;T&gt;::type,
    typename std::enable_if&lt;
        !std::is_lvalue_reference&lt;T &amp;&amp;&gt;::value
        || std::is_const&lt;TRR&gt;::value
        || !std::is_pod&lt;TRR&gt;::value
    &gt;::type* = nullptr
&gt;
void UNUSED(T &amp;&amp; v) {
    static_cast&lt;void&gt;(v);
}

template&lt;
    typename T,
    typename TRR = typename std::remove_reference&lt;T&gt;::type,
    typename std::enable_if&lt;
        std::is_lvalue_reference&lt;T &amp;&amp;&gt;::value
        &amp;&amp; !std::is_const&lt;TRR&gt;::value
        &amp;&amp; std::is_pod&lt;TRR&gt;::value
    &gt;::type* = nullptr
&gt;
void UNUSED(T &amp;&amp; v) {
    memset(&amp;v, 0xBD, sizeof(TRR)); // or 0xDECAFBAD pattern, etc.
}

#endif


Anything cleaner/simpler to achieve the same effect, or ideas to make it better?
Missing headers

This code needs

#include &lt;type_traits&gt;
#include &lt;cstring&gt;


Use sizeof operator on a value

While we can write sizeof (type), in this case we have a value, and we can use it here - sizeof will read through the reference, saving us some work:

std::memset(&amp;v, 0xBD, sizeof v);


Reduce repetition

There are two expressions that need to be maintained in parallel in the std::enable_if template.  We can refactor these into a single trait template:

template&lt;typename T&gt;
struct is_mutable_pod_lvalue
    : std::integral_constant&lt;bool,
                             std::is_lvalue_reference&lt;T&amp;&amp;&gt;::value
                             &amp;&amp; !std::is_const&lt;typename std::remove_reference&lt;T&gt;::type&gt;::value
                             &amp;&amp; std::is_pod&lt;typename std::remove_reference&lt;T&gt;::type&gt;::value&gt;
{};


Then the functions reduce to

template&lt;typename T&gt;
typename std::enable_if&lt;!is_mutable_pod_lvalue&lt;T&gt;::value&gt;::type
UNUSED(T &amp;&amp; v) {
    static_cast&lt;void&gt;(v);
}

template&lt;typename T&gt;
typename std::enable_if&lt;is_mutable_pod_lvalue&lt;T&gt;::value&gt;::type
UNUSED(T &amp;&amp; v) {
    std::memset(&amp;v, 0xBD, sizeof v);
}


In C++14, we could use the _t and _v forms to avoid typing ::type and ::value respectively, and in C++17, we could use std::bool_constant instead of std::integral_constant. 

If we were using C++17, we could further reduce to a single function, by moving the test within the function body:

template&lt;typename T&gt;
UNUSED(T&amp;&amp; v) {
    if constexpr (is_mutable_pod_lvalue&lt;T&gt;::value)
        std::memset(&amp;v, 0xBD, sizeof v);
}


Now we're no longer using is_mutable_pod_value more than once, we can just inline it back again:

template&lt;typename T&gt;
void UNUSED(T&amp;&amp; v) {
    static const bool is_mutable_pod_lvalue =
        std::is_lvalue_reference&lt;T&amp;&amp;&gt;::value
        &amp;&amp; !std::is_const&lt;typename std::remove_reference&lt;T&gt;::type&gt;::value
        &amp;&amp; std::is_pod&lt;typename std::remove_reference&lt;T&gt;::type&gt;::value;

    if constexpr ((is_mutable_pod_lvalue)
        std::memset(&amp;v, 0xBD, sizeof v);
}


Enhancement: accept multiple arguments

Here's a varargs template that makes it easier to use:

template&lt;typename T, typename... U&gt;
void UNUSED(T&amp;&amp; v, U&amp;&amp;... u)
{
    UNUSED(v);
    UNUSED(u...);
}


Again, C++17 makes this simpler, with fold expressions:

template&lt;typename... T&gt;
void UNUSED(T&amp;&amp;... v)
{
    (UNUSED(v) , ...);
}


A definition is required when NDEBUG is set

Probably just an oversight, but the code is missing an #else block.  It's probably worth reordering so that the positive branch comes first (confusing because NDEBUG is itself a negative...).  Further, since the only difference between the debug and non-debug cases it the use of std::memset() in one of the implementations, we can reduce the scope of #ifdef to just that (at a small cost to non-debug compilation times):

template&lt;typename T&gt;
typename std::enable_if&lt;is_mutable_pod_lvalue&lt;T&gt;::value&gt;::type
UNUSED(T&amp;&amp; v)
{
    static_cast&lt;void&gt;(v);
#ifndef NDEBUG
    std::memset(&amp;v, 0xBD, sizeof v);
#endif
}


Revised code

#include &lt;type_traits&gt;
#include &lt;cstring&gt;
template&lt;typename T&gt;
struct is_mutable_pod_lvalue
    : std::integral_constant&lt;bool,
                             std::is_lvalue_reference&lt;T&amp;&amp;&gt;::value
                             &amp;&amp; !std::is_const&lt;typename std::remove_reference&lt;T&gt;::type&gt;::value
                             &amp;&amp; std::is_pod&lt;typename std::remove_reference&lt;T&gt;::type&gt;::value&gt;
{};

template&lt;typename T&gt;
typename std::enable_if&lt;!is_mutable_pod_lvalue&lt;T&gt;::value&gt;::type
UNUSED(T&amp;&amp; v)
{
    static_cast&lt;void&gt;(v);
}

template&lt;typename T&gt;
typename std::enable_if&lt;is_mutable_pod_lvalue&lt;T&gt;::value&gt;::type
UNUSED(T&amp;&amp; v)
{
    static_cast&lt;void&gt;(v);
#ifndef NDEBUG
    std::memset(&amp;v, 0xBD, sizeof v);
#endif
}

template&lt;typename T, typename... U&gt;
void UNUSED(T&amp;&amp; v, U&amp;&amp;... u)
{
    UNUSED(v);
    UNUSED(u...);
}




#include &lt;memory&gt;
void f(int i, const int ci, int&amp; ri, const int&amp; cri, int *pi,
       std::unique_ptr&lt;int&gt; ui, std::unique_ptr&lt;int&gt;&amp;&amp; rrui)
{
#ifdef TEST_UNUSED
    UNUSED(i, ci, ri, cri, pi, ui, rrui);
#endif
}


Four compilations are required to test this fully for all combinations of TEST_UNUSED and NDEBUG.