Причина, по которой это не работает, заключается в том, что если enable_if
получает истинное значение, ваше объявление будет преобразовано в
template<class ForwardIterator, void>
Это недопустимый способ объявления шаблона. Если вместо этого он скажет class = void
, у него будет безымянный параметр со значением по умолчанию void, и он будет работать.
template<class ForwardIterator,
class = typename std::enable_if<
std::is_same<typename std::iterator_traits<ForwardIterator>::value_type, int>::value
>::type>
Это, однако, связано с другой проблемой. Значение по умолчанию для параметра шаблона не является частью его подписи. Поэтому, если мы попытаемся добавить перегрузку, где мы заменим int
на double
, мы получим ошибку из-за того, что две функции шаблона имеют одинаковую сигнатуру.
Чтобы решить эту вторую проблему, вместо этого мы делаем вторуюпараметр не типовой параметр. Это сделает сигнатуры уникальными по отношению друг к другу.
template<class ForwardIterator,
typename std::enable_if<
std::is_same<typename std::iterator_traits<ForwardIterator>::value_type, int>::value
>::type* = nullptr>
Теперь, если enable_if
успешно, мы получим void*
параметр не-типа со значением по умолчанию nullptr
, и мы можем добавитьПерегрузки с различными требованиями в нашем enable_if
, если мы хотим.
SFINAE обычно используется для выбора между различными функциями в зависимости от критериев, если вы хотите ограничить шаблон только, static_assert
, скорее всего, лучшеoption.
Легче писать, легче читать, и вы получаете гораздо более наглядное сообщение об ошибке при сбое компиляции.