Ошибка замены не является ошибкой (SFINAE) касается только замены аргументов шаблона во время разрешения перегрузки. Все это в основном означает, что если подстановка выведенных аргументов шаблона в процессе выяснения, какая функция вызывать, приведет к созданию недопустимого типа или выражения, то это не приведет к ошибке компиляции, а просто приведет к соответствующему функция больше не рассматривается как потенциальный кандидат на вызов функции. Только материал, который появляется в объявлении шаблона функции (или частичной специализации класса или шаблона переменной), может быть объектом SFINAE. Потенциальная реализация определения шаблона функции происходит после того, как определено, какую функцию вызывать точно. Если подстановка аргумента шаблона приводит к недопустимой конструкции во время создания определения шаблона функции, такой сбой подстановки очень часто будет ошибкой.
В вашем конкретном случае, учитывая два варианта
String(std::size_t);
template <class ITER_WRAP>
String(const ITER_WRAP &iterator_begin_end);
вызов конструктора String
с аргументом типа int
выберет специализацию шаблона String<int>
, поскольку для вызова String(std::size_t)
требуется интегральное повышение, которое имеет худший рейтинг конверсии, чем точное совпадение, String<int>
дает вам