Рассмотрим этот фрагмент кода, в котором используется общепринятая идиома: шаблон функции создает экземпляр шаблона класса, специализированного на выведенном типе, как видно из std::make_unique
и std::make_tuple
, например:
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) };
}
В контексте «универсальных ссылок» Скотта Мейерса аргумент make_foo
является универсальной ссылкой, поскольку его тип — U&&
, где выводится U
. Аргумент конструктора foo
не является универсальной ссылкой, потому что, хотя его тип T&&
, T
(в общем случае) не выводится.
Но в случае, когда конструктор foo
вызывается make_foo
, мне кажется, что имеет смысл рассматривать аргумент конструктора foo
как универсальную ссылку, поскольку T
был выведен шаблоном функции make_foo
. . Будут применяться одни и те же правила свертывания ссылок, так что тип v
будет одинаковым в обеих функциях. В этом случае можно сказать, что и T
, и U
были выведены.
Итак, мой вопрос двоякий:
- Имеет ли смысл думать об аргументе конструктора
foo
как об универсальной ссылке в ограниченных случаях, когдаT
выводится вызывающей стороной в контексте универсальной ссылки, как в моем примере? - В моем примере оба варианта использования
std::forward
разумны?