Rotate a given number of variables in-place
Issues (for me)
I get a couple of errors when I try and compile.
This error I have a feeling is caused because you are using a more up to date compiler (I presume this is a C++17 feature).
if constexpr (sizeof...(Tail) &gt; 0) {
   ^^^^^^^^^

This problem causes my second error (because I remove constexpr to make it compile):
rt.cpp:12:6: note: candidate function template not viable: requires at least 2 arguments, but 1 was provided
auto rotate_left_inner(T&amp; first, T&amp; second, Args&amp;... args)

Assuming that constexpr forces that expression to be evaluated at compile time and thus removes that whole block of code. Then it should compile.
Review
You and I differ on how we like to express the return value. I believe we have already had the discussion. So I just want to point it out for other readers.
// You
auto rotate_left(Head&amp; first, Tail&amp;... args)
    -&gt; void

// Me
void rotate_left(Head&amp; first, Tail&amp;... args)

But I don't see anything wrong with yours either, its a simple stylistic thing.
Personally I don't like recursive template meta programming. Two reasons:

This was because when templates were first introduced there was a recursive limit on most compilers. I think this is purely historical now as most compilers have really huge recursive limits now.

Recursive template functions needed a terminating version of the function. But this new constexpr if statement seems to be in response to that. So you no longer need a special case and it can be handled by the compiler.


So it looks like both my reasons for disliking recursive template functions have been addressed by the new version of the language.
But I still prefer the style of the unrolling the argument loop in a function. So I present my version of the same function to show readers how it is done without using recursion (template iterative style).
#include &lt;type_traits&gt;
#include &lt;utility&gt;
#include &lt;tuple&gt;


template&lt;typename T, std::size_t... index&gt;
void rotate_left_inner(T&amp;&amp; tuple, std::index_sequence&lt;index...&gt; const&amp;)
{
    auto tmp = std::move(std::get&lt;0&gt;(tuple));
    auto mover = {0, (std::get&lt;index&gt;(tuple) = std::move(std::get&lt;index + 1&gt;(tuple)), 0)...};
    std::get&lt;sizeof...(index)&gt;(tuple) = std::move(tmp);
}

template&lt;typename... List&gt;
void rotate_left(List&amp;... args)
{
    rotate_left_inner(std::tie(args...), std::make_index_sequence&lt;sizeof...(args) - 1&gt;());
}

#include &lt;iostream&gt;

int main()
{
    int t1 = 5;
    int t2 = 6;
    int t3 = 7;

    rotate_left(t1, t2, t3);
    std::cout &lt;&lt; t1 &lt;&lt; &quot; &quot; &lt;&lt; t2 &lt;&lt; &quot; &quot; &lt;&lt; t3 &lt;&lt; &quot;\n&quot;;

    rotate_left(t1);
    std::cout &lt;&lt; t1 &lt;&lt; &quot; &quot; &lt;&lt; t2 &lt;&lt; &quot; &quot; &lt;&lt; t3 &lt;&lt; &quot;\n&quot;;
}