123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- [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 `minimum_category`]
- `minimum_category` takes two iterator categories or two iterator traversal tags
- and returns the one that is the weakest (i.e. least advanced). For example:
- static_assert(
- is_same<
- minimum_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]
|