Вы действительно используете полиморфизм во время компиляции, который отправляет на основе статического типа объекта.
Итератор категории объединен в цепочку наследованием (а не самим итератором), поэтомучто:
InputIterator <- ForwardIterator <- BidirectionalIterator <- RandomAccessIterator
(тоже должно быть OutputIterator
, но это не имеет значения)
Используя iterator_traits
, вы можете получить категорию итератора, связанную с текущим итератором.Вы создаете фиктивное значение, а затем включается процесс разрешения перегрузки. Предположим для примера, что у вас есть 3 перегрузки:
template <class T>
foo(T a, std::random_access_iterator_tag const&);
// beware of slicing (in general)
template <class T>
foo(T a, std::forward_iterator_tag const&);
template <class T>
foo(T a, std::input_iterator_tag const&);
Теперь предположим, что я использую foo
с итератором списка:
list<int> myList;
foo(myList.begin());
Затем 4 foo
находятся в области видимости (разрешение имени).
foo(T)
немедленно отбрасывается (неверный номер аргумента) foo(T, std::random_access_iterator_tag const&)
отбрасывается, потому что нет преобразования из std::bidirectional_iterator_tag
в std::random_access_iterator_tag
.
Таким образом 2 foo
совместимы (примечание: если мы использовали OutputIterator, мыничего бы не осталось, и на этом этапе возникнет ошибка компиляции).
Затем мы наконец перейдем к ранжирующей части процесса разрешения перегрузки.Поскольку std::forward_iterator_tag
является «более близким» (более непосредственным) основанием, чем std::input_iterator_tag
, поэтому оно имеет более высокий рейтинг.
foo(T, std::forward_iterator_tag const&)
.
Обратите внимание на статическую частьоб этом, хотя.
std::forward_iterator_tag const& tag = std::vector<int>::iterator_category;
foo(myVector.begin(), tag);
Здесь, хотя tag
действительно является (динамическим) std::random_access_iterator_tag
, система воспринимается как std::forward_iterator_tag
, и, таким образом, та же перегрузка, что и вышебудет выбран.