template<template<class...> class Template, class... Ts>
concept Instantiatible = requires { typename Template<Ts...>; };
// ошибка: краткий синтаксис работает только с концептами над типами
template<Instantiatible<int, float, bool> Template>
void foo(Template<int, float, bool> t) { ... }
Пример конечно тривиальный, но "в жизни" это тоже бывает полезно. При параметризации кода по контейнеру для данных часто нужен любой контейнер, обладающий какими-то свойствами (например любой упорядоченный ассоциативный контейнер). Ещё один юзкейс -- policy based design, где политики обычно являются шаблонами, удовлетворяющими каким-либо свойствам. В обоих случаях приятнее сразу писать какой именно шаблон нужен, а не дописывать всё повторно в requires-clause.
С ходу в голову не приходит хороших причин, почему для типов этот сахар поддерживается, а для других сущностей -- нет.
Аналогичная ситуация наблюдается и с нетиповыми шаблонными аргументами вроде целых чисел, однако не уверен, что их поддержка имеет практический смысл.
Так сейчас можно:
А вот так нельзя:
Пример конечно тривиальный, но "в жизни" это тоже бывает полезно. При параметризации кода по контейнеру для данных часто нужен любой контейнер, обладающий какими-то свойствами (например любой упорядоченный ассоциативный контейнер). Ещё один юзкейс -- policy based design, где политики обычно являются шаблонами, удовлетворяющими каким-либо свойствам. В обоих случаях приятнее сразу писать какой именно шаблон нужен, а не дописывать всё повторно в requires-clause. С ходу в голову не приходит хороших причин, почему для типов этот сахар поддерживается, а для других сущностей -- нет.
Аналогичная ситуация наблюдается и с нетиповыми шаблонными аргументами вроде целых чисел, однако не уверен, что их поддержка имеет практический смысл.