Для вашего массива длина массива равна 3 (например, name.length = 3). Но поскольку он хранит элемент, начинающийся с индекса 0, он имеет максимальный индекс 2.
Итак, вместо 'i ** & lt; = name.length' вы должны написать 'i & lt; ** name.length' чтобы избежать «ArrayIndexOutOfBoundsException».
Насколько я знаю, нешаблонная функция всегда предпочитается для шаблонной обработки функции во время разрешения перегрузки.
Это верно, только когда специализация и не обрабатывает по шаблону, точно то же. Дело обстоит не так здесь все же. Когда Вы звоните uct u3(u1)
, наборы перегрузки добираются
uct(const uct &)
uct(uct &) // from the template
Теперь, так как u1
не константа, которую это должно было бы применить преобразование константы для вызова конструктора копии. Назвать шаблонную специализацию - потребности ничего не сделать, так как это - точное совпадение. Это означает шаблонные победы, поскольку это - лучшее соответствие.
Для остановки этой вещи можно сделать, использовать SFINAE для ограничения шаблонной функции, которую только назовут, когда T
не uct
. Это было бы похоже
template <typename T, std::enable_if_t<!std::is_same_v<uct, std::decay_t<T>>, bool> = true>
uct(T &&) { std::cerr << "template" << std::endl; }
, Когда конструктора копии судят, чтобы быть названным, шаблонная перегрузка выбрана. Насколько я знаю, что нешаблонная функция всегда предпочитается для шаблонной обработки функции во время разрешения перегрузки. Почему конструктор копии обрабатывается по-другому?
template <typename T>
uct(T &&) { std::cerr << "template" << std::endl; }
// ^^
причина, шаблонная версия выбрана, состоит в том, потому что компилятор способен
для генерации конструктора с подписью (T &)
, которая соответствует лучше и поэтому выбрана.
при изменении подписи с uct u1
до const uct u1
тогда, она соответствовала бы конструктору копии (так как u1
не константа для начала).
при изменении подписи с uct(const uct &)
до uct(uct&)
, это было бы лучшее соответствие, и это предпочло бы это шаблонной версии.
кроме того, эти uct(uct&&)
был бы выбран, если Вы использовали uct u3(std::move(u1));
Для фиксации этого, можно использовать SFINAE для отключения перегрузки, когда T
совпадает с uct
:
template <typename T, std::enable_if_t<!std::is_same_v<std::decay_t<T>, uct>>>
uct(T&&)
{
std::cerr << "template" << std::endl;
}
Проблема состоит в том, что у шаблонного конструктора есть не квалификация const
, в то время как у нешаблонного конструктора копии есть константа спецификатора в ее параметре. Если Вы объявите объект u1
как const
объект тогда, нешаблонного конструктора копии вызовут.
Из Стандарта C++ (7 Стандартных преобразований)
1 Стандартное преобразование является неявными преобразованиями со встроенным значением. Пункт 7 перечисляет полный набор таких преобразований. Стандартная последовательность преобразования является последовательностью стандартных преобразований в следующем порядке:
(1.4) — Нулю или одному преобразованию квалификации
Так конструктор копии нужно одно стандартное преобразование, в то время как шаблонный конструктор sies не требует такого преобразования.