UNUSED() with teeth in C++11 debug builds
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.