[section:traits Type Traits]

[h2 Overview]

Have you ever wanted to write a generic function that can operate
on any kind of dereferenceable object?  If you have, you've
probably run into the problem of how to determine the type that the
object "points at":

   template <class Dereferenceable>
   void f(Dereferenceable p)
   {
       *what-goes-here?* value = \*p;
       ...
   }


[h2 `pointee`]

It turns out to be impossible to come up with a fully-general
algorithm to do determine *what-goes-here* directly, but it is
possible to require that `pointee<Dereferenceable>::type` is
correct. Naturally, `pointee` has the same difficulty: it can't
determine the appropriate `::type` reliably for all
`Dereferenceable`\ s, but it makes very good guesses (it works
for all pointers, standard and boost smart pointers, and
iterators), and when it guesses wrongly, it can be specialized as
necessary:

  namespace boost
  {
    template <class T>
    struct pointee<third_party_lib::smart_pointer<T> >
    {
        typedef T type;
    };
  }

[h2 `indirect_reference`]

`indirect_reference<T>::type` is rather more specialized than
`pointee`, and is meant to be used to forward the result of
dereferencing an object of its argument type.  Most dereferenceable
types just return a reference to their pointee, but some return
proxy references or return the pointee by value.  When that
information is needed, call on `indirect_reference`.

Both of these templates are essential to the correct functioning of
[link iterator.specialized.indirect `indirect_iterator`].

[h2 `min_category`]

`min_category` takes one or more iterator categories or iterator traversal tags
and returns the one that is the weakest (i.e. least advanced). For example:

  static_assert(
      is_same<
          min_category<
              std::forward_iterator_tag,
              std::random_access_iterator_tag
          >::type,
          std::forward_iterator_tag
      >::value,
      "Unexpected minimum_category result"
  );

[h2 Iterator category and traversal tags manipulation]

The library provides several utilities to simplify conversions between iterator categories
and traversal tags:

* `iterator_category_to_traversal<C>::type` - the metafunction takes an iterator category `C` and returns
the corresponding traversal tag.
* `iterator_traversal<T>::type` - a shorthand for `iterator_category_to_traversal<iterator_category<T>::type>::type`.
* `pure_traversal_tag<T>::type` - the metafunction takes a tag `T` which derives from one of the iterator traversal tags
and returns that traversal tag. `T` may also derive from other tags describing the iterator (e.g. whether this is a `const`-iterator
or not), these additional tags are not considered.
* `pure_iterator_traversal<T>::type` - a shorthand for `pure_traversal_tag<iterator_traversal<T>::type>::type`.

[h2 Reference]

[h3 `pointee`]

  template <class Dereferenceable>
  struct pointee
  {
      typedef /* see below */ type;
  };

[*Requires:] For an object `x` of type `Dereferenceable`, `*x`
  is well-formed.  If `++x` is ill-formed it shall neither be
  ambiguous nor shall it violate access control, and
  `Dereferenceable::element_type` shall be an accessible type.
  Otherwise `iterator_traits<Dereferenceable>::value_type` shall
  be well formed. \[Note: These requirements need not apply to
  explicit or partial specializations of `pointee`\]

`type` is determined according to the following algorithm, where
`x` is an object of type `Dereferenceable`:

  if ( ++x is ill-formed )
  {
      return Dereferenceable::element_type
  }
  else if (*x is a mutable reference to
           std::iterator_traits<Dereferenceable>::value_type)
  {
      return iterator_traits<Dereferenceable>::value_type
  }
  else
  {
      return iterator_traits<Dereferenceable>::value_type const
  }

[h3 `indirect_reference`]

  template <class Dereferenceable>
  struct indirect_reference
  {
      typedef /* see below */ type;
  };

[*Requires:] For an object `x` of type `Dereferenceable`, `*x`
  is well-formed.  If `++x` is ill-formed it shall neither be
  ambiguous nor shall it violate access control, and
  `pointee<Dereferenceable>::type&` shall be well-formed.
  Otherwise `iterator_traits<Dereferenceable>::reference` shall
  be well formed.  \[Note: These requirements need not apply to
  explicit or partial specializations of `indirect_reference`\]

`type` is determined according to the following algorithm, where
`x` is an object of type `Dereferenceable`:

  if ( ++x is ill-formed )
      return pointee<Dereferenceable>::type&
  else
      std::iterator_traits<Dereferenceable>::reference

[h3 `minimum_category`]

  template <typename C1, typename C2>
  struct minimum_category
  {
      typedef /* see below */ type;
  };

[*Requires:] Both `C1` and `C2` shall be standard iterator categories or
  iterator traversal tags.

`type` is determined according to the following algorithm, where `c1` is an
object of type `C1` and `c2` is an object of type `C2`:

  if (c1 is convertible to c2)
      return C2;
  else
      return C1;

[note The above definition relies on the fact that the more restricting categories
and traversal tags are convertible to the less restricting ones.]

[h3 `iterator_category_to_traversal`]

  template <typename C>
  struct iterator_category_to_traversal
  {
      typedef /* see below */ type;
  };

[*Requires:] `C` shall be a standard iterator category or an
  iterator traversal tag.

If `C` is an iterator traversal tag or convertible to one, `type` equivalent to `C`.
Otherwise, `type` is defined to the closest iterator traversal tag matching `C`.

[h3 `iterator_traversal`]

  template <typename Iterator>
  struct iterator_traversal
  {
      typedef typename iterator_category_to_traversal<
          typename iterator_category<Iterator>::type
      >::type type;
  };

[*Requires:] `Iterator` shall be an iterator.

[h3 `pure_traversal_tag`]

  template <typename T>
  struct pure_traversal_tag
  {
      typedef /* see below */ type;
  };

[*Requires:] `T` shall be convertible to an iterator traversal tag.

`type` is defined to be the most advanced traversal tag `Tag` so that `T` is convertible to `Tag`.

[h3 `pure_iterator_traversal`]

  template <typename Iterator>
  struct pure_iterator_traversal
  {
      typedef typename pure_traversal_tag<
          typename iterator_traversal<Iterator>::type
      >::type type;
  };

[*Requires:] `Iterator` shall be an iterator.

[endsect]
