Концепты против SFINAE
Вопрос
Как ограничить шаблон функции только числовыми типами? Покажите путь через SFINAE и через концепты и сравните.
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
SFINAE: `std::enable_if_t<std::is_arithmetic_v<T>>` в возвращаемом типе или параметре шаблона
Минусы SFINAE: нечитаемо, огромные ошибки, сложно делать взаимоисключающие перегрузки
Концепты: `template <Number T>` или `requires`, стандартные `std::integral`, `std::floating_point`
Перегрузка по концептам: выбирается более ограниченный кандидат
Ошибки сообщают, какое требование не выполнено
static_assert как простой вариант, если перегрузка не нужна
Что могут спросить следом
- Чем requires-клауза отличается от requires-выражения?
- Как работает subsumption концептов?
Разбор
До C++20 ограничение делали через SFINAE: добавляли в сигнатуру std::enable_if_t<std::is_arithmetic_v<T>, int> = 0 или подставляли его в возвращаемый тип. Если тип не подходил, подстановка проваливалась, и перегрузка тихо исчезала из списка кандидатов. Работает, но читается плохо, ошибки на несколько экранов, а для двух взаимоисключающих перегрузок приходится аккуратно писать противоположные условия. В C++20 я пишу концепт template <class T> concept Number = std::integral<T> || std::floating_point<T>; и ограничиваю шаблон template <Number T>. Требования видны в объявлении, ошибка говорит, какое требование не выполнено, а при перегрузке компилятор выбирает более ограниченный вариант, если один концепт включает другой. Для сложных требований есть requires-выражения, проверяющие, что выражение компилируется и даёт нужный тип. Если перегрузка не нужна и хочется просто понятной ошибки, хватает static_assert внутри шаблона.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.
Ещё по теме «Шаблоны и концепты»
- Дерево отрезков с операцией как параметром шаблона
- Обобщённая функция статистики для чисел и строк
- Один бинарный поиск на все случаи: предикат как параметр шаблона
- Вывод T при передаче по значению
- Член зависимой базы
- extern template
- Fold-выражения
- Как компилируются шаблоны