Есть шаблон, например : template
Подскажите, как мне ограничить тип, чтобы typename было только либо int, либо double
Ответ
Есть четыре вида шаблонов - шаблоны функций, классов, переменных и псевдонимы типов (using), для разных видов шаблонов ограничения можно задавать по разному.
Само условие проверки лучше поместить в отдельный trait, чтобы не повторять это условие в каждом шаблоне на который надо наложить ограничения:
template
static_assert
Если цель - это выдать ошибку компиляции, то внутри тела шаблона функции и класса можно использовать static_assert
Для шаблонов переменных надо использовать вспомогательную функцию, в которой будет static_assert, для псевдонимов (alias) можно использовать вспомогательный класс.
template
template
Однако в шаблонах класса static_assert срабатывает только при создании объектов, и он не помешает написать X
std::enable_if_t в параметре шаблона
Для генерации ошибки компиляции можно добавить шаблонный параметр со значением по умолчанию, но это меняет арность шаблона.
template
template
template
template
Такую проверку можно обойти, явно указав этот параметр шаблона: X
Прочие способы использования std::enable_if_t
std::enable_if_t
struct empty {};
template
template
template
template
template
SFINAE
Функции могут быть перегружены, по этому для функций ошибка подстановки шаблона приводит только к тому что этот шаблон убирается из списка перегрузки (SFINAE). Это можно использовать совместно с удалением функций:
template
template
Для типов отличных от int и double будет использована первая перегрузка, которая удалена. Для int и double будет использована вторая.
Дополнительный (третий) параметр шаблона нужен чтобы шаблоны как-то отличались - в данном случае у них разная арность.
Этот код можно записать более просто:
template
template
Тогда при использовании int и double первая (удаленная) перегрузка будет прятаться, а при использовании других типов - она будет видна, и будет возникать ошибка "неоднозначный вызов перегруженной функции", потому что будут видны обе перегрузки.
Разумеется вторая перегрузка не обязательно должна быть удаленной. Можно использовать механизм SFINAE для того чтобы иметь одну перегрузку для int и double, а другую перегрузку - для остальных типов. Как писалось ранее, перегрузки должны чем-то отличаться, по этому у них должны быть разные сигнатуры, или разное количество или виды параметров шаблона:
template
template
В будущем (С++17 или позже) можно будет использовать концепции, которые заменят большинство использований enable_if, однако это будет нескоро (скорей всего вместе с Ranges TS).
Комментариев нет:
Отправить комментарий