source: NonGTP/Boost/boost/iterator/detail/facade_iterator_category.hpp @ 857

Revision 857, 6.8 KB checked in by igarcia, 18 years ago (diff)
Line 
1// Copyright David Abrahams 2003. Use, modification and distribution is
2// subject to the Boost Software License, Version 1.0. (See accompanying
3// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4#ifndef FACADE_ITERATOR_CATEGORY_DWA20031118_HPP
5# define FACADE_ITERATOR_CATEGORY_DWA20031118_HPP
6
7# include <boost/iterator/iterator_categories.hpp>
8
9# include <boost/static_assert.hpp>
10
11# include <boost/mpl/or.hpp>  // used in iterator_tag inheritance logic
12# include <boost/mpl/and.hpp>
13# include <boost/mpl/if.hpp>
14# include <boost/mpl/eval_if.hpp>
15# include <boost/mpl/identity.hpp>
16
17# include <boost/type_traits/is_same.hpp>
18# include <boost/type_traits/is_const.hpp>
19# include <boost/type_traits/is_reference.hpp>
20# include <boost/type_traits/is_convertible.hpp>
21
22# include <boost/type_traits/is_same.hpp>
23
24# include <boost/iterator/detail/config_def.hpp> // try to keep this last
25
26# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
27#  include <boost/detail/indirect_traits.hpp>
28# endif
29
30//
31// iterator_category deduction for iterator_facade
32//
33
34// forward declaration
35namespace boost { struct use_default; }
36
37namespace boost { namespace detail  {
38
39struct input_output_iterator_tag
40  : std::input_iterator_tag
41{
42    // Using inheritance for only input_iterator_tag helps to avoid
43    // ambiguities when a stdlib implementation dispatches on a
44    // function which is overloaded on both input_iterator_tag and
45    // output_iterator_tag, as STLPort does, in its __valid_range
46    // function.  I claim it's better to avoid the ambiguity in these
47    // cases.
48    operator std::output_iterator_tag() const
49    {
50        return std::output_iterator_tag();
51    }
52};
53
54//
55// True iff the user has explicitly disabled writability of this
56// iterator.  Pass the iterator_facade's Value parameter and its
57// nested ::reference type.
58//
59template <class ValueParam, class Reference>
60struct iterator_writability_disabled
61# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY // Adding Thomas' logic?
62  : mpl::or_<
63        is_const<Reference>
64      , boost::detail::indirect_traits::is_reference_to_const<Reference>
65      , is_const<ValueParam>
66    >
67# else
68  : is_const<ValueParam>
69# endif
70{};
71
72
73//
74// Convert an iterator_facade's traversal category, Value parameter,
75// and ::reference type to an appropriate old-style category.
76//
77// If writability has been disabled per the above metafunction, the
78// result will not be convertible to output_iterator_tag.
79//
80// Otherwise, if Traversal == single_pass_traversal_tag, the following
81// conditions will result in a tag that is convertible both to
82// input_iterator_tag and output_iterator_tag:
83//
84//    1. Reference is a reference to non-const
85//    2. Reference is not a reference and is convertible to Value
86//
87template <class Traversal, class ValueParam, class Reference>
88struct iterator_facade_default_category
89  : mpl::eval_if<
90        mpl::and_<
91            is_reference<Reference>
92          , is_convertible<Traversal,forward_traversal_tag>
93        >
94      , mpl::eval_if<
95            is_convertible<Traversal,random_access_traversal_tag>
96          , mpl::identity<std::random_access_iterator_tag>
97          , mpl::if_<
98                is_convertible<Traversal,bidirectional_traversal_tag>
99              , std::bidirectional_iterator_tag
100              , std::forward_iterator_tag
101            >
102        >
103      , typename mpl::eval_if<
104            mpl::and_<
105                is_convertible<Traversal, single_pass_traversal_tag>
106               
107                // check for readability
108              , is_convertible<Reference, ValueParam>
109            >
110          , mpl::identity<std::input_iterator_tag>
111          , mpl::identity<Traversal>
112        >
113    >
114{
115};
116
117// True iff T is convertible to an old-style iterator category.
118template <class T>
119struct is_iterator_category
120  : mpl::or_<
121        is_convertible<T,std::input_iterator_tag>
122      , is_convertible<T,std::output_iterator_tag>
123    >
124{
125};
126
127template <class T>
128struct is_iterator_traversal
129  : is_convertible<T,incrementable_traversal_tag>
130{};
131
132//
133// A composite iterator_category tag convertible to Category (a pure
134// old-style category) and Traversal (a pure traversal tag).
135// Traversal must be a strict increase of the traversal power given by
136// Category.
137//
138template <class Category, class Traversal>
139struct iterator_category_with_traversal
140  : Category, Traversal
141{
142# if 0
143    // Because of limitations on multiple user-defined conversions,
144    // this should be a good test of whether convertibility is enough
145    // in the spec, or whether we need to specify inheritance.
146    operator Category() const { return Category(); }
147    operator Traversal() const { return Traversal(); }
148# endif
149   
150# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
151    // Make sure this isn't used to build any categories where
152    // convertibility to Traversal is redundant.  Should just use the
153    // Category element in that case.
154    BOOST_STATIC_ASSERT(
155        !(is_convertible<
156              typename iterator_category_to_traversal<Category>::type
157            , Traversal
158          >::value));
159
160    BOOST_STATIC_ASSERT(is_iterator_category<Category>::value);
161    BOOST_STATIC_ASSERT(!is_iterator_category<Traversal>::value);
162    BOOST_STATIC_ASSERT(!is_iterator_traversal<Category>::value);
163#  if !BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310))
164    BOOST_STATIC_ASSERT(is_iterator_traversal<Traversal>::value);
165#  endif
166# endif
167};
168
169// Computes an iterator_category tag whose traversal is Traversal and
170// which is appropriate for an iterator
171template <class Traversal, class ValueParam, class Reference>
172struct facade_iterator_category_impl
173{
174# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
175    BOOST_STATIC_ASSERT(!is_iterator_category<Traversal>::value);
176# endif
177   
178    typedef typename iterator_facade_default_category<
179        Traversal,ValueParam,Reference
180    >::type category;
181   
182    typedef typename mpl::if_<
183        is_same<
184            Traversal
185          , typename iterator_category_to_traversal<category>::type
186        >
187      , category
188      , iterator_category_with_traversal<category,Traversal>
189    >::type type;
190};
191
192//
193// Compute an iterator_category for iterator_facade
194//
195template <class CategoryOrTraversal, class ValueParam, class Reference>
196struct facade_iterator_category
197  : mpl::eval_if<
198        is_iterator_category<CategoryOrTraversal>
199      , mpl::identity<CategoryOrTraversal> // old-style categories are fine as-is
200      , facade_iterator_category_impl<CategoryOrTraversal,ValueParam,Reference>
201    >
202{
203};
204
205}} // namespace boost::detail
206
207# include <boost/iterator/detail/config_undef.hpp>
208
209#endif // FACADE_ITERATOR_CATEGORY_DWA20031118_HPP
Note: See TracBrowser for help on using the repository browser.