aboutsummaryrefslogtreecommitdiff
path: root/cutl/details/boost/iterator/detail/facade_iterator_category.hpp
blob: 6bdd37a1eede758a8535a8f97b433bfb01302a3c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
// Copyright David Abrahams 2003. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef FACADE_ITERATOR_CATEGORY_DWA20031118_HPP
# define FACADE_ITERATOR_CATEGORY_DWA20031118_HPP

# include <cutl/details/boost/iterator/iterator_categories.hpp>

# include <cutl/details/boost/mpl/or.hpp>  // used in iterator_tag inheritance logic
# include <cutl/details/boost/mpl/and.hpp>
# include <cutl/details/boost/mpl/if.hpp>
# include <cutl/details/boost/mpl/eval_if.hpp>
# include <cutl/details/boost/mpl/identity.hpp>
# include <cutl/details/boost/mpl/assert.hpp>

# include <cutl/details/boost/type_traits/is_same.hpp>
# include <cutl/details/boost/type_traits/is_const.hpp>
# include <cutl/details/boost/type_traits/is_reference.hpp>
# include <cutl/details/boost/type_traits/is_convertible.hpp>

# include <cutl/details/boost/type_traits/is_same.hpp>

# include <cutl/details/boost/iterator/detail/config_def.hpp> // try to keep this last

# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
#  include <cutl/details/boost/detail/indirect_traits.hpp>
# endif

//
// iterator_category deduction for iterator_facade
//

// forward declaration
namespace cutl_details_boost { struct use_default; }

namespace cutl_details_boost { namespace detail  {

struct input_output_iterator_tag
  : std::input_iterator_tag
{
    // Using inheritance for only input_iterator_tag helps to avoid
    // ambiguities when a stdlib implementation dispatches on a
    // function which is overloaded on both input_iterator_tag and
    // output_iterator_tag, as STLPort does, in its __valid_range
    // function.  I claim it's better to avoid the ambiguity in these
    // cases.
    operator std::output_iterator_tag() const
    {
        return std::output_iterator_tag();
    }
};

//
// True iff the user has explicitly disabled writability of this
// iterator.  Pass the iterator_facade's Value parameter and its
// nested ::reference type.
//
template <class ValueParam, class Reference>
struct iterator_writability_disabled
# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY // Adding Thomas' logic?
  : mpl::or_<
        is_const<Reference>
      , cutl_details_boost::detail::indirect_traits::is_reference_to_const<Reference>
      , is_const<ValueParam>
    >
# else 
  : is_const<ValueParam>
# endif 
{};


//
// Convert an iterator_facade's traversal category, Value parameter,
// and ::reference type to an appropriate old-style category.
//
// If writability has been disabled per the above metafunction, the
// result will not be convertible to output_iterator_tag.
//
// Otherwise, if Traversal == single_pass_traversal_tag, the following
// conditions will result in a tag that is convertible both to
// input_iterator_tag and output_iterator_tag:
//
//    1. Reference is a reference to non-const
//    2. Reference is not a reference and is convertible to Value
//
template <class Traversal, class ValueParam, class Reference>
struct iterator_facade_default_category
  : mpl::eval_if<
        mpl::and_<
            is_reference<Reference>
          , is_convertible<Traversal,forward_traversal_tag>
        >
      , mpl::eval_if<
            is_convertible<Traversal,random_access_traversal_tag>
          , mpl::identity<std::random_access_iterator_tag>
          , mpl::if_<
                is_convertible<Traversal,bidirectional_traversal_tag>
              , std::bidirectional_iterator_tag
              , std::forward_iterator_tag
            >
        >
      , typename mpl::eval_if<
            mpl::and_<
                is_convertible<Traversal, single_pass_traversal_tag>
                
                // check for readability
              , is_convertible<Reference, ValueParam>
            >
          , mpl::identity<std::input_iterator_tag>
          , mpl::identity<Traversal>
        >
    >
{
};

// True iff T is convertible to an old-style iterator category.
template <class T>
struct is_iterator_category
  : mpl::or_<
        is_convertible<T,std::input_iterator_tag>
      , is_convertible<T,std::output_iterator_tag>
    >
{
};

template <class T>
struct is_iterator_traversal
  : is_convertible<T,incrementable_traversal_tag>
{};

//
// A composite iterator_category tag convertible to Category (a pure
// old-style category) and Traversal (a pure traversal tag).
// Traversal must be a strict increase of the traversal power given by
// Category.
//
template <class Category, class Traversal>
struct iterator_category_with_traversal
  : Category, Traversal
{
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
    // Make sure this isn't used to build any categories where
    // convertibility to Traversal is redundant.  Should just use the
    // Category element in that case.
    BOOST_MPL_ASSERT_NOT((
        is_convertible<
              typename iterator_category_to_traversal<Category>::type
            , Traversal
          >));

    BOOST_MPL_ASSERT((is_iterator_category<Category>));
    BOOST_MPL_ASSERT_NOT((is_iterator_category<Traversal>));
    BOOST_MPL_ASSERT_NOT((is_iterator_traversal<Category>));
#  if !BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310))
    BOOST_MPL_ASSERT((is_iterator_traversal<Traversal>));
#  endif 
# endif 
};

// Computes an iterator_category tag whose traversal is Traversal and
// which is appropriate for an iterator
template <class Traversal, class ValueParam, class Reference>
struct facade_iterator_category_impl
{
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
    BOOST_MPL_ASSERT_NOT((is_iterator_category<Traversal>));
# endif 
    
    typedef typename iterator_facade_default_category<
        Traversal,ValueParam,Reference
    >::type category;
    
    typedef typename mpl::if_<
        is_same<
            Traversal
          , typename iterator_category_to_traversal<category>::type
        >
      , category
      , iterator_category_with_traversal<category,Traversal>
    >::type type;
};

//
// Compute an iterator_category for iterator_facade
//
template <class CategoryOrTraversal, class ValueParam, class Reference>
struct facade_iterator_category
  : mpl::eval_if<
        is_iterator_category<CategoryOrTraversal>
      , mpl::identity<CategoryOrTraversal> // old-style categories are fine as-is
      , facade_iterator_category_impl<CategoryOrTraversal,ValueParam,Reference>
    >
{
};

}} // namespace cutl_details_boost::detail

# include <cutl/details/boost/iterator/detail/config_undef.hpp>

#endif // FACADE_ITERATOR_CATEGORY_DWA20031118_HPP