Universal reference in a class template I'm writing a templatized container and wanted to use an universal reference for the Add(T&amp;&amp; object) function. Check out isocpp if you need an update on your universal/rvalue references. A quick example from that page states that, since the class is templatized, T&amp;&amp; is fully specified and therefore a rvalue, not an universal reference.

template &lt;class T, class Allocator = allocator&lt;T&gt; &gt;
class vector {
public:
    ...
    void push_back(T&amp;&amp; x);       // fully specified parameter type ⇒ no type deduction;
    ...                          // &amp;&amp; ≡ rvalue reference
};


This means that I cannot pass lvalues to the push_back function above.

vector&lt;T&gt; list;

list.Add(T()); // rvalue, compiles fine.

T data;
list.Add(data); // lvalue, does not compile.


In the case of std::vector this is solved by having a push_back(const T&amp; object) overload.
However, since the code in my Add function is quite complex, I didn't want to copy it over. 

However, if I am to templatize my add function, it does become universal reference. So I came up with the following code. 

#include &lt;iostream&gt;
#include &lt;type_traits&gt;
#include &lt;vector&gt;
using namespace std;

template &lt;class T&gt;
class Container
{
    public:
    template &lt;class UR = T&gt;
    void Add(UR&amp;&amp; object)
    {
        static_assert(std::is_same&lt;std::remove_cv_t&lt;std::remove_reference_t&lt;UR&gt;&gt;, T&gt;::value, "UR and T should be the same!");
        m_Vector.push_back(std::forward&lt;UR&gt;(object));
    }
    std::vector&lt;T&gt; m_Vector;
};

class Data
{
    public:
    int x;
    int y;
};

int main() {
    Container&lt;Data&gt; list;
    Data d;
    list.Add(d);
    return 0;
}


I've added the static assert to make sure that people do not actually templatize the Add function. Does anyone know a cleaner solution, since this feels a bit of template magic? Should I follow the std method and just copy my add function (which is a bit more complex than this minimal example)? Can anyone come up with a case where my solution will not work?

Here is a small ideone version for you to play around with.
Your solution is principally correct. If you want to play nice with potential generic traits (at the cost of a potentially uglier error message), you'd replace the static_assert with SFINAE:

template &lt;
    class UR = T,
    class TypeMustBeT = std::enable_if_t&lt;std::is_same&lt;std::remove_reference_t&lt;UR&gt;, T&gt;::value&gt;
&gt;
void Add(UR&amp;&amp; object)
{
    m_Vector.push_back(std::forward&lt;UR&gt;(object));
}


This way, the function Add will not exist at all when UR is not a forwarding reference for T1.

If you don't like the "template magic" involved in this and/or the compiler errors generated from misuse, you can solve this by providing the two strongly-typed overloads as std does and forward to a common private implementation:

void Add(const T&amp; object)
{
  AddImpl(object);
}

void Add(T&amp;&amp; object)
{
  AddImpl(std::move(object));
}

private:
template &lt;class UR&gt;
void AddImpl(UR&amp;&amp; object)
{
    static_assert(std::is_same&lt;std::remove_cv_t&lt;std::remove_reference_t&lt;UR&gt;&gt;, T&gt;::value, "UR and T should be the same!");
    m_Vector.push_back(std::forward&lt;UR&gt;(object));
}


This way, you can keep the static_assert-using version and keep the static assertion just to check your code's correctness, not the client code's.

Note that the static_assert needs to do std::remove_cv after std::remove_reference, otherwise it will fail for UR = const T&amp;. The same applies to the original code in the question too.

Unrelated to the question at hand, but I assume using namespace std; is for this reduced example only and is not present in your real code. It's very bad practice to put that into header files in real code.



1 Note that "forwarding reference" is the preferred term instead of "universal reference," since it captures the semantics better.