Компилятору требуется при разрешении перегрузки отбрасывать перегрузку шаблона из набора функций-кандидатов, когда InputIt
не выводится как тип итератора (более формально, когда он не удовлетворяет концепции LegacyInputIterator
- см. note (5) на этой странице ).
Удаление перегрузок в пользовательском коде выполняется с помощью техники SFINAE , хотя реализация компилятора может использовать что-то другое - они не требуется строго использовать легальный код C ++. Например, мой (MinGW) компилятор реализует его с помощью SFINAE:
template<typename _InputIterator,
typename = std::_RequireInputIter<_InputIterator>>
vector(_InputIterator __first, _InputIterator __last,
const allocator_type& __a = allocator_type());
, где _RequireInputIter
равно
template<typename _InIter>
using _RequireInputIter = typename
enable_if<is_convertible<typename
iterator_traits<_InIter>::iterator_category,
input_iterator_tag>::value>::type;
Это требование вступило в силу с C ++ 11, поэтому до это, вы могли на самом деле вызвать неправильный конструктор. Если мы немного изменим ваш пример:
#include <iostream>
template <typename T>
struct A {
A(size_t n, const T &v) { std::cout << n << " x " << v << std::endl; }
template <typename I>
A(I first, I last) { std::cout << first << " ... " << last << std::endl; }
};
int main() {
A<size_t> a(3, 42);
}
, теперь он напечатает 3 ... 42
.