Search code examples
c++c++11template-meta-programmingrvalue-referenceforwarding-reference

Is a parameter type with `T&&` in it and `T` deduced always a universal reference?


With reference to

template<typename T>
void fun(ParamType param); // ParamType is some form of T, e.g. T, T&, T const, ...

fun(expr); // expr is an expression

I know that && "somewhere" in ParamType is not enough for ParamType to be a universal reference, for instance ParamType = std::vector<T>&& is an rvalue reference. && needs to be just beside the template parameter T for it (T&&) to possibly be a universal reference.

But I also know that T&& "somewhere" in ParamType is still not enough, for instance ParamType = std::remove_reference_t<T&&> is not a universal reference.

Therefore, I was almost asking are there/what are the requirements on the "form" of ParamType for it to be a forwarding reference?.

However, by doing a bit of research, I kind of feel I need to ask a more "binary" question:

Assuming for simplicity that T is the only template parameter and, consequently, that ParamType is only function (in the math sense) of T, is it correct to say that if both of these are true

  • T appears in ParamType the form of T&&
  • fun deduces T and PramType (i.e. the T doesn't need to be passed via fun<T>)

then ParamType is a universal reference?

In other words, is ParamType always a universal reference if it has a T&& in it with T deduced?


Solution

  • what are the requirements on the "form" of ParamType for it to be a forwarding reference?.

    From the standard (latest draft):

    [temp.deduct.call] A forwarding reference is an rvalue reference to a cv-unqualified template parameter that does not represent a template parameter of a class template


    Is a parameter type with T&& in it and T deduced always a universal reference?

    It doesn't matter what is "in" the type, but what the type is. If it is a cv-unqualified rvalue reference to a template parameter of a function, then it is a forwarding reference.

    For example, Foo<T&&> has T&& "in it", but it is not a forwarding reference. Nor can ParamType be a forwarding reference since it isn't a template argument of the function.