std::input_iterator_tag,std::output_iterator_tag,std::forward_iterator_tag,(3)

NAME
std::input_iterator_tag,std::output_iterator_tag,std::forward_iterator_tag, - std::input_iterator_tag,std::output_iterator_tag,std::forward_iterator_tag,

Synopsis
                        std::contiguous_iterator_tag
   Defined in header <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 (5)
   bidirectional_iterator_tag {};
   struct contiguous_iterator_tag : public random_access_iterator_tag (6) (since C++20)
   {};
   Defines the category of an iterator. Each tag is an empty type.

Notes
   There is no separate tag for LegacyContiguousIterator. That is, it is not possible
   to tell a LegacyContiguousIterator based on its iterator_category.
   To define specialized algorithm for contiguous iterators, use the
   contiguous_iterator concept.
   (since C++20)
   There are no correspondences between output_iterator_tag and the output_iterator
   concept. Setting iterator_concept to output_iterator_tag only indicates that the
   type does not model input_iterator.

Example
   Common technique for algorithm selection based on iterator category tags is to use a
   dispatcher function (the alternative is std::enable_if).
   The iterator tag classes are also used in the corresponding concepts definitions to
   denote the requirements, which can't be expressed in terms of usage patterns alone.
   (since C++20) // Run this code
 #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
 }

Output:
 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

See also
   iterator base class to ease the definition of required types for simple
   (deprecated in C++17) iterators
                        (class template)
   iterator_traits provides uniform interface to the properties of an iterator
                        (class template)