Skip to content

Commit 801a056

Browse files
Add virtual polymorphic view and iterator classes
1 parent 27128d7 commit 801a056

File tree

11 files changed

+626
-106
lines changed

11 files changed

+626
-106
lines changed

CMakeLists.txt

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,8 @@ include(GNUInstallDirs)
7070
add_library(beman.any_view INTERFACE)
7171
add_library(beman::any_view ALIAS beman.any_view)
7272
set_target_properties(beman.any_view PROPERTIES CXX_EXTENSIONS OFF)
73-
target_compile_features(beman.any_view INTERFACE cxx_std_20)
74-
# TODO: implement non-template friend function and remove this suppression
75-
target_compile_options(
76-
beman.any_view
77-
INTERFACE $<$<CXX_COMPILER_ID:GNU>:-Wno-non-template-friend>
78-
)
73+
# TODO: discuss removal of std::unreachable() to revert to C++20
74+
target_compile_features(beman.any_view INTERFACE cxx_std_23)
7975
target_include_directories(
8076
beman.any_view
8177
INTERFACE

CMakePresets.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
"generator": "Ninja",
88
"binaryDir": "${sourceDir}/build/${presetName}",
99
"cacheVariables": {
10-
"CMAKE_CXX_STANDARD": "20",
1110
"CMAKE_EXPORT_COMPILE_COMMANDS": true
1211
}
1312
},

include/beman/any_view/any_view.hpp

Lines changed: 94 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55

66
#include <beman/any_view/concepts.hpp>
77
#include <beman/any_view/config.hpp>
8+
#include <beman/any_view/detail/intrusive_small_ptr.hpp>
89
#include <beman/any_view/detail/iterator.hpp>
10+
#include <beman/any_view/detail/view_adaptor.hpp>
11+
#include <beman/any_view/detail/view_interface.hpp>
912

1013
#if BEMAN_ANY_VIEW_USE_FLAGS()
1114

@@ -54,9 +57,23 @@ class any_view : public std::ranges::view_interface<any_view<ElementT, OptionsV,
5457
((OptionsV & any_view_options::BEMAN_ANY_VIEW_OPTION()) == any_view_options::BEMAN_ANY_VIEW_OPTION());
5558
static constexpr bool simple = (OptionsV & any_view_options::simple) == any_view_options::simple;
5659

60+
using interface_type = detail::view_interface<iterator_concept, ElementT, RefT, RValueRefT, DiffT>;
61+
// inplace storage sufficient for a vtable pointer and a std::vector<T>
62+
detail::intrusive_small_ptr<interface_type, 4 * sizeof(void*)> view_ptr;
63+
64+
template <class RangeT>
65+
using adaptor_type =
66+
detail::view_adaptor<iterator_concept, ElementT, RefT, RValueRefT, DiffT, std::views::all_t<RangeT>>;
67+
68+
template <class RangeT>
69+
static consteval auto get_in_place_adaptor_type() {
70+
return std::in_place_type<adaptor_type<RangeT>>;
71+
}
72+
5773
public:
5874
template <detail::viewable_range_compatible_with<any_view> RangeT>
59-
constexpr any_view(RangeT&&);
75+
constexpr any_view(RangeT&& range)
76+
: view_ptr(get_in_place_adaptor_type<RangeT>(), std::views::all(std::forward<RangeT>(range))) {}
6077

6178
constexpr any_view(const any_view&)
6279
requires copyable
@@ -71,15 +88,24 @@ class any_view : public std::ranges::view_interface<any_view<ElementT, OptionsV,
7188
constexpr auto operator=(any_view&&) noexcept -> any_view& = default;
7289

7390
[[nodiscard]] constexpr auto begin() -> iterator
74-
requires(not simple);
91+
requires(not simple)
92+
{
93+
return view_ptr->begin();
94+
}
7595

7696
[[nodiscard]] constexpr auto begin() const -> iterator
77-
requires simple;
97+
requires simple
98+
{
99+
return view_ptr->begin();
100+
}
78101

79102
[[nodiscard]] constexpr auto end() const { return std::default_sentinel; }
80103

81104
[[nodiscard]] constexpr auto size() const -> size_type
82-
requires sized;
105+
requires sized
106+
{
107+
return view_ptr->size();
108+
}
83109
};
84110

85111
#elif BEMAN_ANY_VIEW_USE_TRAITS()
@@ -103,9 +129,28 @@ class any_view : public std::ranges::view_interface<any_view<ElementT, RangeTrai
103129
detail::BEMAN_ANY_VIEW_OPTION_(or_v)<false, RangeTraitsT>;
104130
static constexpr bool simple = detail::simple_or_v<false, RangeTraitsT>;
105131

132+
using interface_type =
133+
detail::view_interface<iterator_concept, ElementT, reference_type, rvalue_reference_type, difference_type>;
134+
// inplace storage sufficient for a vtable pointer and a std::vector<T>
135+
detail::intrusive_small_ptr<interface_type, 4 * sizeof(void*)> view_ptr;
136+
137+
template <class RangeT>
138+
using adaptor_type = detail::view_adaptor<iterator_concept,
139+
ElementT,
140+
reference_type,
141+
rvalue_reference_type,
142+
difference_type,
143+
std::views::all_t<RangeT>>;
144+
145+
template <class RangeT>
146+
static consteval auto get_in_place_adaptor_type() {
147+
return std::in_place_type<adaptor_type<RangeT>>;
148+
}
149+
106150
public:
107151
template <detail::viewable_range_compatible_with<any_view> RangeT>
108-
constexpr any_view(RangeT&&);
152+
constexpr any_view(RangeT&& range)
153+
: view_ptr(get_in_place_adaptor_type<RangeT>(), std::views::all(std::forward<RangeT>(range))) {}
109154

110155
constexpr any_view(const any_view&)
111156
requires copyable
@@ -120,15 +165,24 @@ class any_view : public std::ranges::view_interface<any_view<ElementT, RangeTrai
120165
constexpr auto operator=(any_view&&) noexcept -> any_view& = default;
121166

122167
[[nodiscard]] constexpr auto begin() -> iterator
123-
requires(not simple);
168+
requires(not simple)
169+
{
170+
return view_ptr->begin();
171+
}
124172

125173
[[nodiscard]] constexpr auto begin() const -> iterator
126-
requires simple;
174+
requires simple
175+
{
176+
return view_ptr->begin();
177+
}
127178

128179
[[nodiscard]] constexpr auto end() const { return std::default_sentinel; }
129180

130181
[[nodiscard]] constexpr auto size() const -> size_type
131-
requires sized;
182+
requires sized
183+
{
184+
return view_ptr->size();
185+
}
132186
};
133187

134188
#elif BEMAN_ANY_VIEW_USE_NAMED()
@@ -151,9 +205,28 @@ class any_view : public std::ranges::view_interface<any_view<ElementT, OptionsV>
151205
OptionsV.BEMAN_ANY_VIEW_OPTION();
152206
static constexpr bool simple = OptionsV.simple;
153207

208+
using interface_type =
209+
detail::view_interface<iterator_concept, ElementT, reference_type, rvalue_reference_type, difference_type>;
210+
// inplace storage sufficient for a vtable pointer and a std::vector<T>
211+
detail::intrusive_small_ptr<interface_type, 4 * sizeof(void*)> view_ptr;
212+
213+
template <class RangeT>
214+
using adaptor_type = detail::view_adaptor<iterator_concept,
215+
ElementT,
216+
reference_type,
217+
rvalue_reference_type,
218+
difference_type,
219+
std::views::all_t<RangeT>>;
220+
221+
template <class RangeT>
222+
static consteval auto get_in_place_adaptor_type() {
223+
return std::in_place_type<adaptor_type<RangeT>>;
224+
}
225+
154226
public:
155227
template <detail::viewable_range_compatible_with<any_view> RangeT>
156-
constexpr any_view(RangeT&&);
228+
constexpr any_view(RangeT&& range)
229+
: view_ptr(get_in_place_adaptor_type<RangeT>(), std::views::all(std::forward<RangeT>(range))) {}
157230

158231
constexpr any_view(const any_view&)
159232
requires copyable
@@ -168,15 +241,24 @@ class any_view : public std::ranges::view_interface<any_view<ElementT, OptionsV>
168241
constexpr auto operator=(any_view&&) noexcept -> any_view& = default;
169242

170243
[[nodiscard]] constexpr auto begin() -> iterator
171-
requires(not simple);
244+
requires(not simple)
245+
{
246+
return view_ptr->begin();
247+
}
172248

173249
[[nodiscard]] constexpr auto begin() const -> iterator
174-
requires simple;
250+
requires simple
251+
{
252+
return view_ptr->begin();
253+
}
175254

176255
[[nodiscard]] constexpr auto end() const { return std::default_sentinel; }
177256

178257
[[nodiscard]] constexpr auto size() const -> size_type
179-
requires sized;
258+
requires sized
259+
{
260+
return view_ptr->size();
261+
}
180262
};
181263

182264
#endif

include/beman/any_view/concepts.hpp

Lines changed: 10 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,42 +3,20 @@
33
#ifndef BEMAN_ANY_VIEW_CONCEPTS_HPP
44
#define BEMAN_ANY_VIEW_CONCEPTS_HPP
55

6+
#include <beman/any_view/detail/concepts.hpp>
67
#include <beman/any_view/range_traits.hpp>
7-
#include <iterator>
88

99
namespace beman::any_view {
1010
namespace detail {
1111

12-
template <class IterT, class IterConceptT>
13-
concept input_iterator_compatible_with =
14-
std::input_or_output_iterator<IterT> and
15-
(not std::derived_from<IterConceptT, std::input_iterator_tag> or std::input_iterator<IterT>);
16-
17-
template <class IterT, class IterConceptT>
18-
concept forward_iterator_compatible_with =
19-
input_iterator_compatible_with<IterT, IterConceptT> and
20-
(not std::derived_from<IterConceptT, std::forward_iterator_tag> or std::forward_iterator<IterT>);
21-
22-
template <class IterT, class IterConceptT>
23-
concept bidirectional_iterator_compatible_with =
24-
forward_iterator_compatible_with<IterT, IterConceptT> and
25-
(not std::derived_from<IterConceptT, std::bidirectional_iterator_tag> or std::bidirectional_iterator<IterT>);
26-
27-
template <class IterT, class IterConceptT>
28-
concept random_access_iterator_compatible_with =
29-
bidirectional_iterator_compatible_with<IterT, IterConceptT> and
30-
(not std::derived_from<IterConceptT, std::random_access_iterator_tag> or std::random_access_iterator<IterT>);
31-
32-
template <class IterT, class IterConceptT>
33-
concept contiguous_iterator_compatible_with =
34-
random_access_iterator_compatible_with<IterT, IterConceptT> and
35-
(not std::derived_from<IterConceptT, std::contiguous_iterator_tag> or std::contiguous_iterator<IterT>);
36-
37-
template <class RangeRefT, class TraitsRefT, class IterConceptT>
38-
concept contiguous_reference_convertible_to =
39-
std::convertible_to<RangeRefT, TraitsRefT> and
40-
(not std::derived_from<IterConceptT, std::contiguous_iterator_tag> or
41-
std::convertible_to<std::remove_reference_t<RangeRefT> (*)[], std::remove_reference_t<TraitsRefT> (*)[]>);
12+
template <class IteratorT, class RangeTraitsT>
13+
concept iterator_compatible_with =
14+
contiguous_iterator_compatible_with<IteratorT, iterator_concept_t<RangeTraitsT>> and
15+
contiguous_reference_convertible_to<std::iter_reference_t<IteratorT>,
16+
reference_type_t<RangeTraitsT>,
17+
iterator_concept_t<RangeTraitsT>> and
18+
std::convertible_to<std::iter_rvalue_reference_t<IteratorT>, rvalue_reference_type_t<RangeTraitsT>> and
19+
std::convertible_to<std::iter_difference_t<IteratorT>, difference_type_t<RangeTraitsT>>;
4220

4321
template <class RangeT, class RangeTraitsT>
4422
concept sized_range_compatible_with = not RangeTraitsT::sized or std::ranges::sized_range<RangeT>;
@@ -48,13 +26,7 @@ concept borrowed_range_compatible_with = not RangeTraitsT::borrowed or std::rang
4826

4927
template <class RangeT, class RangeTraitsT>
5028
concept range_compatible_with =
51-
std::ranges::range<RangeT> and
52-
contiguous_iterator_compatible_with<std::ranges::iterator_t<RangeT>, iterator_concept_t<RangeTraitsT>> and
53-
contiguous_reference_convertible_to<std::ranges::range_reference_t<RangeT>,
54-
reference_type_t<RangeTraitsT>,
55-
iterator_concept_t<RangeTraitsT>> and
56-
std::convertible_to<std::ranges::range_rvalue_reference_t<RangeT>, rvalue_reference_type_t<RangeTraitsT>> and
57-
std::convertible_to<std::ranges::range_difference_t<RangeT>, difference_type_t<RangeTraitsT>> and
29+
std::ranges::range<RangeT> and iterator_compatible_with<std::ranges::iterator_t<RangeT>, RangeTraitsT> and
5830
sized_range_compatible_with<RangeT, RangeTraitsT> and borrowed_range_compatible_with<RangeT, RangeTraitsT>;
5931

6032
template <class ViewT, class RangeTraitsT>

include/beman/any_view/detail/concepts.hpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,37 @@ concept simple_range = std::ranges::range<RangeT> and std::ranges::range<const R
1414
std::same_as<std::ranges::iterator_t<RangeT>, std::ranges::iterator_t<const RangeT>> and
1515
std::same_as<std::ranges::sentinel_t<RangeT>, std::ranges::sentinel_t<const RangeT>>;
1616

17+
template <class IterT, class IterConceptT>
18+
concept input_iterator_compatible_with =
19+
std::input_or_output_iterator<IterT> and
20+
(not std::derived_from<IterConceptT, std::input_iterator_tag> or std::input_iterator<IterT>);
21+
22+
template <class IterT, class IterConceptT>
23+
concept forward_iterator_compatible_with =
24+
input_iterator_compatible_with<IterT, IterConceptT> and
25+
(not std::derived_from<IterConceptT, std::forward_iterator_tag> or std::forward_iterator<IterT>);
26+
27+
template <class IterT, class IterConceptT>
28+
concept bidirectional_iterator_compatible_with =
29+
forward_iterator_compatible_with<IterT, IterConceptT> and
30+
(not std::derived_from<IterConceptT, std::bidirectional_iterator_tag> or std::bidirectional_iterator<IterT>);
31+
32+
template <class IterT, class IterConceptT>
33+
concept random_access_iterator_compatible_with =
34+
bidirectional_iterator_compatible_with<IterT, IterConceptT> and
35+
(not std::derived_from<IterConceptT, std::random_access_iterator_tag> or std::random_access_iterator<IterT>);
36+
37+
template <class IterT, class IterConceptT>
38+
concept contiguous_iterator_compatible_with =
39+
random_access_iterator_compatible_with<IterT, IterConceptT> and
40+
(not std::derived_from<IterConceptT, std::contiguous_iterator_tag> or std::contiguous_iterator<IterT>);
41+
42+
template <class RangeRefT, class TraitsRefT, class IterConceptT>
43+
concept contiguous_reference_convertible_to =
44+
std::convertible_to<RangeRefT, TraitsRefT> and
45+
(not std::derived_from<IterConceptT, std::contiguous_iterator_tag> or
46+
std::convertible_to<std::remove_reference_t<RangeRefT> (*)[], std::remove_reference_t<TraitsRefT> (*)[]>);
47+
1748
} // namespace beman::any_view::detail
1849

1950
#endif // BEMAN_ANY_VIEW_DETAIL_CONCEPTS_HPP

0 commit comments

Comments
 (0)