правило шаблона, правильной формы и нулевой длины пакета

Из принятого ответа на предыдущий вопрос я обнаружил правило Я не знал о шаблонах и корректности

Программа некорректна, диагностика не требуется, если:

  • [...]
  • для каждой допустимой специализации вариативного шаблона требуется пустой пакет параметров шаблона, или
  • [...]

В соответствии с этим правилом (если я правильно понимаю) следующая шаблонная функция некорректна

template <typename ... Ts>
int foo (std::tuple<Ts...> const &)
 { return std::get<sizeof...(Ts)>(std::tuple<int>{42}); }

потому что единственная допустимая специализация требует и пустой пакет параметров Ts....

Но (может быть, потому что я не очень хорошо знаю английский) я не уверен, что пойму это правило в случае шаблона с двумя или более пакетами параметров.

Я имею в виду... следующую функцию foo()

#include <tuple>
#include <iostream>

template <typename ... Ts, typename ... Us>
int foo (std::tuple<Ts...> const &, std::tuple<Us...> const &)
 { return std::get<sizeof...(Ts)+sizeof...(Us)-1U>(std::tuple<int>{42}); }

int main ()
 {
   auto t0 = std::tuple<>{};
   auto t1 = std::tuple<int>{0};

   //std::cout << foo(t0, t0) << std::endl; // compilation error
   std::cout << foo(t0, t1) << std::endl;   // print 42
   std::cout << foo(t1, t0) << std::endl;   // print 42
   //std::cout << foo(t1, t1) << std::endl; // compilation error
 }

хорошо сформирован или плохо сформирован?

Потому что его действительная специализация требует, чтобы Ts... или Us... было пустым (и чтобы другой пакет параметров был точно такого же размера, как 1).

Правило следует интерпретировать в том смысле, что программа плохо сформирована, если есть пустой пакет параметров, который должен быть всегда пустым (поэтому мой пример должен быть правильно сформирован, потому что оба пакета параметров могут быть непустыми) или в том смысле, что неправильно сформирован, если в каждой специализации есть хотя бы пустой пакет параметров, не обязательно одинаковый в каждой специализации (поэтому мой пример должен быть неправильно сформирован)?


person max66    schedule 30.09.2017    source источник
comment
Я думаю, вы ошибочно принимаете специализацию за создание экземпляра. Я имею в виду, что данный пример содержит только шаблонную функцию без каких-либо специализаций.   -  person user7860670    schedule 30.09.2017
comment
Честно говоря, я тоже не совсем понимаю это условие. Однако, если специализация используется там в качестве экземпляра, это не имеет никакого смысла, например, создание экземпляра template<int V, typename...> class foo{}; как foo<0> и foo<1> сделает программу неправильно сформированной, поскольку для обеих специализаций потребуется пустой пакет параметров шаблона.   -  person user7860670    schedule 30.09.2017
comment
@VTT - извините за мой предыдущий комментарий: я неправильно понял пункт 4   -  person max66    schedule 30.09.2017
comment
@VTT - может быть, ты прав; возможно, я неправильно понял полное правило.   -  person max66    schedule 30.09.2017
comment
@VTT - все еще пытаюсь понять ... из книги (общие знания C ++, SC Dewhurst), которую я читал. Специализация шаблона - это то, что вы делаете, когда предоставляете шаблон с набором аргументов шаблона; что касается специализации функции шаблона, когда мы пишем print(12.3), мы подразумеваем специализацию шаблона функции печати с помощью шаблона функции. Согласно этому определению, четыре вызова foo() (два закомментированных) в моем примере вызывают четыре (две) специализации foo(). Вы согласны? (извините, но мне нужно идти, и я уезжаю на несколько часов)   -  person max66    schedule 30.09.2017
comment
Я считаю, что имя того, что происходит с шаблонами при вызове foo(), называется (неявным) созданием экземпляров. Специализация относится к предоставлению альтернативного определения основному шаблону.   -  person Passer By    schedule 30.09.2017
comment
При дальнейшем чтении специализация — это результирующий класс/функция (неявно или явно) применения определенного набора аргументов к шаблону. Согласно стандарту Если специализация шаблона класса не была создана явно или явно не специализирована, специализация шаблона класса создается неявно[...]   -  person Passer By    schedule 30.09.2017
comment
@PasserBy - я немного сбит с толку, потому что привык думать о специализации как об альтернативном определении класса (частичное или полное) или определении функции (только полное). Но я нашел определение, эквивалентное (кажется) тому, что вы расшифровали, и, как мне кажется, в документе, где присутствует правило, смысл специализации второй.   -  person max66    schedule 30.09.2017