- Вы можете использовать пакет параметров шаблона и расширить его во вложенное объявление шаблона параметров шаблона, не являющихся типом. :
Код: Выделить всё
template
struct Outer {
template
void inner(){}
};
Вызов следующих функций-членов в переменная Outer external{}; приводит к следующему результату (Демо - прокомментируйте определенные строки в main, чтобы увидеть выводит компилятор):
Код: Выделить всё
outer.inner();
- GCC: ошибка: неправильное количество аргументов шаблона (2, должно быть 1)
- clang: компилируется
- MSVC: компилируется
Код: Выделить всё
outer.inner();
- GCC: ошибка: неправильное количество аргументов шаблона (2, должно быть 1)
- clang: шаблон-кандидат игнорируется: недопустимый явно указанный аргумент для параметра шаблона «Vals»
- MSVC: не удалось специализировать шаблон функции «void Outer::inner(void)' (за которым следует ICE)
Код: Выделить всё
outer.inner();
- GCC: ICE
- clang: шаблон-кандидат игнорируется: выведено слишком мало аргументы в пользу расширенного пакета «Валс»; нет аргумента для второго расширенного параметра в пакете выведенных аргументов
- MSVC: компилируется
Код: Выделить всё
outer.inner();
- GCC: компилируется
- clang: шаблон-кандидат игнорируется: выведено слишком мало аргументов для расширенного пакета 'Вальс'; нет аргумента для первого расширенного параметра в выведенном пакете аргументов
- MSVC: компилируется
- Благодаря концепциям C++20 теперь синтаксически допустимо(?) расширять пакет параметров шаблона во вложенный список аргументов шаблона, используя параметры ограниченного типа.
Код: Выделить всё
template
concept At = true;
template
struct Outer{
template
void inner(Ts...){}
};
Код: Выделить всё
outer.inner(0, 1);
- GCC: компилируется
- clang: компилируется
- MSVC: компилируется
Код: Выделить всё
outer.inner(0, 1, 2);
- GCC: ошибка: несоответствующая длина пакета аргументов при расширении «At»
- clang: функция-кандидат [с Ts = ] нежизнеспособна: требуется 2 аргумента, но предоставлено 3
- MSVC: связанный ограничения не выполняются
Код: Выделить всё
outer.inner(0);
[*]GCC: ошибка: несоответствующая длина пакета аргументов при расширении «At»[*]clang: шаблон-кандидат игнорируется: выведено слишком мало аргументов для расширенного пакета «Ts»; нет аргумента для второго расширенного параметра в выведенном пакете аргументов
[*]MSVC: связанные ограничения не удовлетворены
Здесь я предполагаю, что GCC и MSVC верны, поскольку они, кажется, ведут себя так же, как и при переписании from, и в этом случае clang также ведет себя как GCC и MSVC (Демо):
Код: Выделить всё
template
struct Outer{
template
requires (At && ...)
void inner(Ts...){}
};
Код: Выделить всё
template
struct Outer{
template
void inner(Ts..., U){}
};
int main() {
Outer outer{}.inner(true, 1, 2.0);
}
Итак, вопрос еще раз, какое поведение является правильным согласно стандарту?
Подробнее здесь: https://stackoverflow.com/questions/791 ... ner-templa