Как выполнить частичную специализацию шаблона с помощью пакета параметров и значения шаблона без типа?

При попытке использовать время компиляции std :: array в вариационном шаблоне, я написал эту частичную специализацию шаблона:

template <typename array_wrapper> struct Test1;
template <std::size_t... A> struct Test1<any_type<std::array<std::size_t, sizeof...(A)>{A...}>> {}; //(2)

что приводит к ошибке компиляции <Expression> has incomplete type and cannot be defined при моих попытках частичной специализации шаблона для Test1 и Test2, когда я пытаюсь его использовать; следовательно, насколько я понимаю, использование (3) не соответствует определению (2):

int main() {
  Test1<any_type<std::array<std::size_t, 2>{1, 2}>> a; // (3)
}

Я не понимаю, почему это так. Экспериментируя с примером, я понимаю, что это происходит, когда я «скрываю» содержимое пакета параметров в моей структуре any_type:

#include <array>

template <auto f> struct any_type;

template <typename array_wrapper> struct Test1;
template <std::size_t... A> struct Test1<any_type<std::array<std::size_t, sizeof...(A)>{A...}>> {};

template <typename array_wrapper> struct Test2;
template <int... A> struct Test2<any_type<std::get<0>(A...)>> {};

template <typename array_wrapper> struct Test3;
template <int A> struct Test3<any_type<A>> {};

int main() {
  //Test1<any_type<std::array<std::size_t, 2>{1, 2}>> a;
  //Test2<any_type<1>> b;
  Test3<any_type<1>> ok;
}

Test1 и Test2 терпят неудачу с той же ошибкой, и Test3 работает нормально. Почему частичная специализация шаблонов «терпит неудачу» в первых двух случаях? Насколько я понимаю, объявление предоставляет «интерфейс» для использования структуры, а аргументы в специализации сопоставляются с фактически предоставленными аргументами.

Код Код можно найти здесь.

Параметры компиляции: я используюg++-10.0 (GCC) 10.0.1 20200124 (experimental) и компилирую с помощью g++ -std=c++2a file.cc, требуется c ++ 2a, потому что я использую параметры шаблона, не являющиеся типами.


person mutableVoid    schedule 27.02.2020    source источник


Ответы (1)


Существует ограниченный набор шаблонов, из которых можно вывести аргументы шаблона. Для аргументов, не относящихся к типу, этот набор равен (из [temp.deduct .type] / 8):

  • type[i]
  • template-name<i> (где имя-шаблона относится к шаблону класса)
  • TT<i>

... вот и все. Ваш Test3 соответствует второй форме, а два других совсем не совпадают.

Непонятно, как вообще будет работать пример Test2. Пример Test1 может быть тем, что мы хотим рассмотреть, поскольку использование параметров шаблона, не относящихся к типу, расширяется после C ++ 20, но это просто не то, что в настоящее время является допустимым.

person Barry    schedule 27.02.2020