Consider this snippet of code, which uses the common idiom of having a function template construct an instance of a class template specialized on a deduced type, as seen with std::make_unique
and std::make_tuple
, for example:
template <typename T>
struct foo
{
std::decay_t<T> v_;
foo(T&& v) : v_(std::forward<T>(v)) {}
};
template <typename U>
foo<U> make_foo(U&& v)
{
return { std::forward<U>(v) };
}
In the context of Scott Meyers' "universal references", the argument to
make_foo
is a universal reference because its type is U&&
where U
is
deduced. The argument to the constructor of foo
is not a universal reference
because although its type is T&&
, T
is (in general) not deduced.
But in the case in which the constructor of foo
is called by make_foo
, it
seems to me that it might make sense to think of the argument to the constructor
of foo
as being a universal reference, because T
has been deduced by the
function template make_foo
. The same reference collapsing rules will apply
so that the type of v
is the same in both functions. In this case, both T
and U
can be said to have been deduced.
So my question is twofold:
- Does it make sense to think of the argument to the constructor of
foo
as being a universal reference in the limited cases in whichT
has been deduced within a universal reference context by the caller, as in my example? - In my example, are both uses of
std::forward
sensible?
std::move(v)
inside the original constructor – Obala