Какая польза от подстановки — это не сбой

#c #sfinae

#c #sfinae

Вопрос:

У меня есть класс Jav::String, который я использую для шаблонов.

  class String
 {
  String();
  String(std::size_t);

  template <class ITER_WRAP>
  String(const ITER_WRAP amp;iterator_begin_end);
 }
  

Я ожидаю, что когда я вызываю string с целым числом со знаком, таким как MAX_PATH , это вызовет перегрузку std::size_t aka unsigned int; поскольку я ожидаю, что подстановка не является сбоем! По сути, int не имеет элементов begin, end, поэтому замена должна завершиться неудачей, и эта функция не должна быть частью функций-кандидатов.

Однако, к моему ужасу, я получаю ошибку компиляции, const int не имеет начального или конечного элемента.

Когда подстановка является ошибкой, а когда нет. Работает ли это только для типов.

Комментарии:

1. Если вы заинтересованы в SFINAE с нуля, youtube.com/watch?v=Am2is2QCvxY возможно, это будет хорошая презентация для просмотра.

Ответ №1:

Ошибка замены не является ошибкой (SFINAE) касается только замены аргументов шаблона во время разрешения перегрузки. Все, что это в основном означает, это то, что если подстановка выведенных аргументов шаблона в процессе определения того, какую функцию вызывать, приводит к тому, что где-то создается недопустимый тип или выражение, то это не приведет к сбою компиляции, а просто приведет к тому, что соответствующая функция не будет считаться потенциальным кандидатом на функциюбольше не вызывайте. Только материал, который появляется в объявлении шаблона функции (или частичной специализации шаблона класса или переменной), может быть подвержен SFINAE. Потенциальное создание экземпляра определения шаблона функции происходит после того, как было определено, какую функцию точно вызывать. Если подстановка аргумента шаблона приводит к недопустимой конструкции во время создания экземпляра определения шаблона функции, такая ошибка замены в значительной степени будет ошибкой.

В вашем конкретном случае, учитывая два варианта

 String(std::size_t);

template <class ITER_WRAP>
String(const ITER_WRAP amp;iterator_begin_end);
  

вызов String конструктора с аргументом типа int выберет специализацию шаблона String<int> , потому что для вызова String(std::size_t) требуется интегральное продвижение, которое имеет худший ранг преобразования, чем точное совпадение, которое String<int> дает вам…

Комментарии:

1. Спасибо. Я отредактировал свою строку ctor с помощью дополнительного шаблона с именем class X = decltype(X::begin) . проблема в том, что пользователи могут перезаписывать параметры по умолчанию.