std::input_iterator_tag, std::output_iterator_tag, std::forward_iterator_tag, std::bidirectional_iterator_tag, std::random_access_iterator_tag, std::contiguous_iterator_tag
Определён в заголовке <iterator> | ||
|---|---|---|
struct input_iterator_tag {};
| (1) | |
struct output_iterator_tag {};
| (2) | |
struct forward_iterator_tag : public input_iterator_tag {};
| (3) | |
struct bidirectional_iterator_tag : public forward_iterator_tag {};
| (4) | |
struct random_access_iterator_tag : public bidirectional_iterator_tag {};
| (5) | |
struct contiguous_iterator_tag : public random_access_iterator_tag {};
| (6) | (начиная с C++20) |
Определяет категорию итератора. Каждый тег является пустым типом.
Категория итератора
Для каждого типа LegacyIterator It должен быть определён typedef std::iterator_traits<It>::iterator_category в виде псевдонима одного из этих типов-тегов, чтобы указать наиболее конкретную категорию, к которой относится It.
-
input_iterator_tagсоответствует LegacyInputIterator. -
output_iterator_tagсоответствует LegacyOutputIterator. -
forward_iterator_tagсоответствует LegacyForwardIterator. -
bidirectional_iterator_tagсоответствует LegacyBidirectionalIterator. -
random_access_iterator_tagсоответствует LegacyRandomAccessIterator.
Теги категорий итераторов содержат информацию, которую можно использовать для выбора наиболее эффективных алгоритмов с учётом набора требований, подразумеваемого категорией.
Концепция итератораДля каждого типа
Если В любом случае концепция не выполняется, если необходимые операции не поддерживаются, независимо от тега. | (начиная с C++20) |
Примечания
Отдельного тега для LegacyContiguousIterator нет. Иными словами, определить, является ли тип LegacyContiguousIterator, по его iterator_category невозможно. Чтобы определить специализированный алгоритм для непрерывных итераторов, используйте концепцию contiguous_iterator.(начиная с C++20)
Между output_iterator_tag и концепцией output_iterator нет соответствия. Установка iterator_concept в output_iterator_tag лишь указывает, что тип не соответствует input_iterator.
Пример
Распространённый способ выбора алгоритма на основе тегов категорий итераторов — использовать функцию-диспетчер (альтернативой является std::enable_if). Классы тегов итераторов также используются в определениях соответствующих концепций для обозначения требований, которые невозможно выразить только через шаблоны использования.(начиная с C++20)
#include <iostream>
#include <iterator>
#include <list>
#include <vector>
// Using concepts (tag checking is part of the concepts themselves)
template<std::bidirectional_iterator BDIter>
void alg(BDIter, BDIter)
{
std::cout << "1. alg() \t called for bidirectional iterator\n";
}
template<std::random_access_iterator RAIter>
void alg(RAIter, RAIter)
{
std::cout << "2. alg() \t called for random-access iterator\n";
}
// Legacy, using tag dispatch
namespace legacy
{
// Quite often implementation details are hidden in a dedicated namespace
namespace implementation_details
{
template<class BDIter>
void alg(BDIter, BDIter, std::bidirectional_iterator_tag)
{
std::cout << "3. legacy::alg() called for bidirectional iterator\n";
}
template<class RAIter>
void alg(RAIter, RAIter, std::random_access_iterator_tag)
{
std::cout << "4. legacy::alg() called for random-access iterator\n";
}
} // namespace implementation_details
template<class Iter>
void alg(Iter first, Iter last)
{
implementation_details::alg(first, last,
typename std::iterator_traits<Iter>::iterator_category());
}
} // namespace legacy
int main()
{
std::list<int> l;
alg(l.begin(), l.end()); // 1.
legacy::alg(l.begin(), l.end()); // 3.
std::vector<int> v;
alg(v.begin(), v.end()); // 2.
legacy::alg(v.begin(), v.end()); // 4.
// std::istreambuf_iterator<char> i1(std::cin), i2;
// alg(i1, i2); // compile error: no matching function for call
// legacy::alg(i1, i2); // compile error: no matching function for call
}
Вывод:
1. alg() called for bidirectional iterator 3. legacy::alg() called for bidirectional iterator 2. alg() called for random-access iterator 4. legacy::alg() called for random-access iterator
См. также
|
(устарело в C++17) | базовый класс, упрощающий определение необходимых типов для простых итераторов (шаблон класса) |
| предоставляет единый интерфейс к свойствам итератора (шаблон класса) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/iterator/iterator_tags