В CPPReference написано, что пакет параметров расширен до указателей, почему?
template<class... Us>
void f(Us... pargs) {}
template<class... Ts>
void g(Ts... args)
{
f(&args...); // “&args...” is a pack expansion
// “&args” is its pattern
}
g(1, 0.2, "a"); // Ts... args expand to int E1, double E2, const char* E3
// &args... expands to &E1, &E2, &E3
// Us... pargs expand to int* E1, double* E2, const char** E3
Почему Us... расширяется до указателей?
Как вы думаете, каким будет Us
?
Вы спрашиваете, почему &args...
создает указатели? &
делает это.
Рассмотрим int n = 0; double d = 0.2; char const* s = "a"; f(&n, &d, &s);
— вы создаете здесь указатели на n
, d
и s
, которые вы передаете f
— это то же самое, что делает g
(с той лишь разницей, что внутри g
указатели нацелены на параметры функции — которые под капотом также являются просто локальными переменными ).
давайте сломаем это.
template<class... Us>
void f(Us... pargs)
// takes any number of parameters by copy
{}
template<class... Ts>
void g(Ts... args)
// takes any number of parameters by copy
{
f(&args...); // each element in pack args is passed by copy then the address of those copies is taken by & operator then the function f deduces types to be <int*,double*,const char**>
}
g(1, 0.2, "a"); // Ts... here expands to <int,double,const char*> since it takes by copy
Ваш комментарий по поводу вызова f
неверен. оператор адреса не применяется к копиям args...
. &
применяется к каждому элементу пакета, и передается адрес каждого объекта в args...
но это не аргументы... хотя вот копии
То, как ваш комментарий читается для меня, звучит так, будто вы говорите, что arg...
копируется при вызове f
, и именно те копии, к которым применяется &
.
Я не понимаю вашего замешательства. У вас есть int, назовем его
E1
, как в комментариях.&E1
— это адресint
, то есть указатель наint
. Теперь примените это ко всему пакету параметров.