Расширение пакета шаблонов Variadic - PullRequest
10 голосов
/ 07 февраля 2012

В В выступлении Андрея о GoingNative 2012 он рассказывает о шаблонах Variadic и объясняет в одном месте пример, показывающий, как работают расширения пакета параметров. Будучи довольно новым для этого предмета, мне было довольно трудно следить за тем, как работает каждый случай. Кто-нибудь может объяснить, как работает расширение при каждом вызове функции gun?

template<class... Ts> void fun(Ts... vs) {
    gun(A<Ts...>::hun(vs)...);
    gun(A<Ts...>::hun(vs...));
    gun(A<Ts>::hun(vs)...);
}

Ответы [ 2 ]

10 голосов
/ 07 февраля 2012

1.

   gun(A<Ts...>::hun(vs)...)
=> gun(A<T1, T2, …, Tn>::hun(vs)...)
=> gun(A<T1, T2, …, Tn>::hun(v1),
       A<T1, T2, …, Tn>::hun(v2),
       …,
       A<T1, T2, …, Tn>::hun(vm))

2

   gun(A<Ts...>::hun(vs...))
=> gun(A<T1, T2, …, Tn>::hun(vs...))
=> gun(A<T1, T2, …, Tn>::hun(v1, v2, …, vm))

Это должно быть очевидно.

3.

   gun(A<Ts>::hun(vs)...)
=> gun(A<T1>::hun(v1), A<T2>::hun(v2), …, A<Tn>::hun(vn))

(В этом случае программа не будет компилироваться, если длины Ts и vs различаются)


... расширит шаблон (который включает в себя любые пакеты параметров), предшествующий ему, что означает, что в foo(Ts, Us, Vs)... каждый член списка Ts, Us, Vs (перечисляется на этапе блокировки ) будет подставлен в этот шаблон, и будет сформирован список через запятую:

   foo(Ts, Us, Vs)...
=> foo(T1, U1, V1), foo(T2, U2, V2), …, foo(Tn, Un, Vn)

И если есть вложенные расширения, самые внутренние шаблоны будут расширены первыми. Следовательно, в случае 1 шаблон Ts сначала будет расширен до T1, T2, …, Tn. И затем шаблон, предшествующий внешнему ..., равен A<T1, T2, …, Tn>::fun(vs) - обратите внимание, что Ts был расширен - поэтому он будет расширен до A<T1, T2, …, Tn>::fun(v1), A<T1, T2, …, Tn>::fun(v2), …, A<T1, T2, …, Tn>::fun(vm) путем замены v1, v2 и т. Д. На vs .

5 голосов
/ 07 февраля 2012

Ответ Кенни ТМ идеален. Мне также просто нравятся образцы. Но так как его ответ абстрактный, я не чувствовал, что добавление демонстраций к его ответу - правильная вещь. Итак, демоверсии для его ответа здесь. Я предполагаю, что его ответ правильный, я сам ничего не знаю. (Если вы проголосуете за это, тоже голосуйте за него)

Очевидно, что это весь псевдокод, просто показывающий расширенные состояния.

void foo<void*,int,char,std::string>(nullptr, 32, '7', "BANANA") {
    //gun(A<Ts...>::hun(vs)...);
    gun(A<void*,int,char,std::string>::hun(nullptr)
       ,A<void*,int,char,std::string>::hun(32)
       ,A<void*,int,char,std::string>::hun('7')
       ,A<void*,int,char,std::string>::hun("BANANA")
       );
    //gun(A<Ts...>::hun(vs...));
    gun(A<void*,int,char,std::string>::hun(nullptr, 32, '7', "BANANA");
    //gun(A<Ts>::hun(vs)...);
    gun(A<void*>::hun(nullptr)
       ,A<int>::hun(32),
       ,A<char>::hun('7'),
       ,A<std::string>::hun("BANANA")
       );
}
...