Skip to content

Commit c916310

Browse files
committed
feat: RangeFor
1 parent f3694e3 commit c916310

File tree

1 file changed

+165
-0
lines changed

1 file changed

+165
-0
lines changed

include/mrdox/Support/RangeFor.hpp

+165
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
//
2+
// This is a derivative work. originally part of the LLVM Project.
3+
// Licensed under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
// Copyright (c) 2023 Vinnie Falco ([email protected])
8+
//
9+
// Official repository: https://github.com/cppalliance/mrdox
10+
//
11+
12+
#ifndef MRDOX_SUPPORT_RANGEFOR_HPP
13+
#define MRDOX_SUPPORT_RANGEFOR_HPP
14+
15+
#include <mrdox/Platform.hpp>
16+
17+
namespace clang {
18+
namespace mrdox {
19+
20+
/** Range to help range-for loops identify first and last.
21+
*/
22+
template<class Container>
23+
class RangeFor
24+
{
25+
Container const& C_;
26+
27+
public:
28+
struct value_type;
29+
using size_type = std::size_t;
30+
using difference_type = std::ptrdiff_t;
31+
using pointer = value_type*;
32+
using reference = value_type&;
33+
using const_pointer = value_type const*;
34+
using const_reference = value_type const&;
35+
36+
class iterator;
37+
38+
explicit
39+
RangeFor(Container const& C) noexcept
40+
: C_(C)
41+
{
42+
}
43+
44+
iterator begin() const noexcept;
45+
iterator end() const noexcept;
46+
};
47+
48+
//------------------------------------------------
49+
50+
template<class Container>
51+
struct RangeFor<Container>::value_type
52+
{
53+
typename Container::value_type const& value;
54+
bool const first;
55+
bool const last;
56+
57+
value_type const* operator->() const noexcept
58+
{
59+
return this;
60+
}
61+
};
62+
63+
//------------------------------------------------
64+
65+
template<class Container>
66+
class RangeFor<Container>::iterator
67+
{
68+
using const_iterator =
69+
typename Container::const_iterator;
70+
71+
const_iterator it_{};
72+
const_iterator begin_;
73+
const_iterator last_;
74+
const_iterator end_;
75+
76+
friend class RangeFor;
77+
friend struct value_type;
78+
79+
iterator(
80+
Container const& C,
81+
const_iterator it) noexcept
82+
: it_(it)
83+
, begin_(C.begin())
84+
, last_(C.begin() != C.end() ?
85+
std::prev(C.end()) : C.end())
86+
, end_(C.end())
87+
{
88+
}
89+
90+
public:
91+
using value_type = typename RangeFor<Container>::value_type;
92+
using pointer = void;
93+
using reference = value_type;
94+
using size_type = std::size_t;
95+
using iterator_category = typename
96+
std::iterator_traits<typename Container::iterator>::iterator_category;
97+
98+
iterator() = default;
99+
iterator(iterator const&) = default;
100+
iterator& operator=(
101+
iterator const&) = default;
102+
103+
iterator& operator++() noexcept
104+
{
105+
++it_;
106+
return *this;
107+
}
108+
109+
iterator operator++(int) noexcept
110+
{
111+
auto temp = *this;
112+
++temp;
113+
return temp;
114+
}
115+
116+
reference operator->() const noexcept
117+
{
118+
return value_type{
119+
*it_,
120+
it_ == begin_,
121+
it_ == last_ };
122+
}
123+
124+
reference operator*() const noexcept
125+
{
126+
return value_type{
127+
*it_,
128+
it_ == begin_,
129+
it_ == last_ };
130+
}
131+
132+
bool operator==(iterator const& it) const noexcept
133+
{
134+
return it_ == it.it_;
135+
}
136+
137+
bool operator!=(iterator const& it) const noexcept
138+
{
139+
return it_ != it.it_;
140+
}
141+
};
142+
143+
//------------------------------------------------
144+
145+
template<class Container>
146+
RangeFor(Container const&) -> RangeFor<Container>;
147+
148+
template<class Container>
149+
auto RangeFor<Container>::begin() const noexcept ->
150+
iterator
151+
{
152+
return iterator(C_, C_.begin());
153+
}
154+
155+
template<class Container>
156+
auto RangeFor<Container>::end() const noexcept ->
157+
iterator
158+
{
159+
return iterator(C_, C_.end());
160+
}
161+
162+
} // mrdox
163+
} // clang
164+
165+
#endif

0 commit comments

Comments
 (0)