-
Notifications
You must be signed in to change notification settings - Fork 70
Expand file tree
/
Copy pathtransform_iterator.hpp
More file actions
146 lines (122 loc) · 4.8 KB
/
Copy pathtransform_iterator.hpp
File metadata and controls
146 lines (122 loc) · 4.8 KB
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
// (C) Copyright David Abrahams 2002.
// (C) Copyright Jeremy Siek 2002.
// (C) Copyright Thomas Witt 2002.
// Distributed under 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 BOOST_ITERATOR_TRANSFORM_ITERATOR_23022003THW_HPP
#define BOOST_ITERATOR_TRANSFORM_ITERATOR_23022003THW_HPP
#include <iterator>
#include <type_traits>
#include <boost/core/use_default.hpp>
#include <boost/core/empty_value.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/iterator/enable_if_convertible.hpp>
#include <boost/iterator/detail/eval_if_default.hpp>
namespace boost {
namespace iterators {
template<
typename UnaryFunction,
typename Iterator,
typename Reference = use_default,
typename Value = use_default
>
class transform_iterator;
namespace detail {
template< typename UnaryFunc, typename Iterator >
struct transform_iterator_default_reference
{
using type = decltype(std::declval< UnaryFunc const& >()(std::declval< typename std::iterator_traits< Iterator >::reference >()));
};
// Compute the iterator_adaptor instantiation to be used for transform_iterator
template< typename UnaryFunc, typename Iterator, typename Reference, typename Value >
struct transform_iterator_base
{
private:
// By default, dereferencing the iterator yields the same as
// the function.
using reference = detail::eval_if_default_t<
Reference,
transform_iterator_default_reference< UnaryFunc, Iterator >
>;
// To get the default for Value: remove any reference on the
// result type, but retain any constness to signal
// non-writability. Note that if we adopt Thomas' suggestion
// to key non-writability *only* on the Reference argument,
// we'd need to strip constness here as well.
using cv_value_type = detail::eval_if_default_t<
Value,
std::remove_reference< reference >
>;
public:
using type = iterator_adaptor<
transform_iterator< UnaryFunc, Iterator, Reference, Value >,
Iterator,
cv_value_type,
use_default, // Leave the traversal category alone
reference
>;
};
} // namespace detail
template< typename UnaryFunc, typename Iterator, typename Reference, typename Value >
class transform_iterator :
public detail::transform_iterator_base< UnaryFunc, Iterator, Reference, Value >::type,
private boost::empty_value< UnaryFunc >
{
friend class iterator_core_access;
private:
using super_t = typename detail::transform_iterator_base< UnaryFunc, Iterator, Reference, Value >::type;
using functor_base = boost::empty_value< UnaryFunc >;
public:
transform_iterator() = default;
transform_iterator(Iterator const& x, UnaryFunc f) :
super_t(x),
functor_base(boost::empty_init_t{}, f)
{}
// don't provide this constructor if UnaryFunc is a
// function pointer type, since it will be 0. Too dangerous.
template< bool Requires = std::is_class< UnaryFunc >::value, typename = typename std::enable_if< Requires >::type >
explicit transform_iterator(Iterator const& x) :
super_t(x)
{}
template<
typename OtherUnaryFunction,
typename OtherIterator,
typename OtherReference,
typename OtherValue,
typename = enable_if_convertible_t< OtherIterator, Iterator >,
typename = enable_if_convertible_t< OtherUnaryFunction, UnaryFunc >
>
transform_iterator(transform_iterator< OtherUnaryFunction, OtherIterator, OtherReference, OtherValue > const& t) :
super_t(t.base()),
functor_base(boost::empty_init_t{}, t.functor())
{}
UnaryFunc functor() const { return functor_base::get(); }
private:
typename super_t::reference dereference() const { return functor_base::get()(*this->base()); }
};
template< typename UnaryFunc, typename Iterator >
inline transform_iterator< UnaryFunc, Iterator > make_transform_iterator(Iterator it, UnaryFunc fun)
{
return transform_iterator< UnaryFunc, Iterator >(it, fun);
}
// Version which allows explicit specification of the UnaryFunc
// type.
//
// This generator is not provided if UnaryFunc is a function
// pointer type, because it's too dangerous: the default-constructed
// function pointer in the iterator be 0, leading to a runtime
// crash.
template< typename UnaryFunc, typename Iterator >
inline typename std::enable_if<
std::is_class< UnaryFunc >::value, // We should probably find a cheaper test than is_class<>
transform_iterator< UnaryFunc, Iterator >
>::type make_transform_iterator(Iterator it)
{
return transform_iterator< UnaryFunc, Iterator >(it);
}
} // namespace iterators
using iterators::transform_iterator;
using iterators::make_transform_iterator;
} // namespace boost
#endif // BOOST_ITERATOR_TRANSFORM_ITERATOR_23022003THW_HPP