Skip to content

Commit 75a090b

Browse files
Use intrinsics for unreachable to support C++20
1 parent 3c614bb commit 75a090b

File tree

5 files changed

+44
-31
lines changed

5 files changed

+44
-31
lines changed

CMakeLists.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,7 @@ 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-
# TODO: discuss removal of std::unreachable() to revert to C++20
74-
target_compile_features(beman.any_view INTERFACE cxx_std_23)
73+
target_compile_features(beman.any_view INTERFACE cxx_std_20)
7574
target_include_directories(
7675
beman.any_view
7776
INTERFACE

include/beman/any_view/detail/iterator_adaptor.hpp

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
#define BEMAN_ANY_VIEW_DETAIL_ITERATOR_ADAPTOR_HPP
55

66
#include <beman/any_view/detail/iterator_interface.hpp>
7+
#include <beman/any_view/detail/utility.hpp>
78

89
#include <compare>
910
#include <iterator>
10-
#include <utility>
1111

1212
namespace beman::any_view::detail {
1313

@@ -34,6 +34,10 @@ class iterator_adaptor : public iterator_interface<IterConceptT, ElementT, RefT,
3434
static constexpr bool random_access = std::derived_from<IterConceptT, std::random_access_iterator_tag>;
3535
static constexpr bool contiguous = std::derived_from<IterConceptT, std::contiguous_iterator_tag>;
3636

37+
static constexpr auto down_cast(const iterator_interface& other) {
38+
return dynamic_cast<const iterator_adaptor*>(std::addressof(other));
39+
}
40+
3741
public:
3842
constexpr iterator_adaptor(IteratorT&& iterator, SentinelT&& sentinel) noexcept(get_noexcept())
3943
: iterator(std::move(iterator)), sentinel(std::move(sentinel)) {}
@@ -42,7 +46,7 @@ class iterator_adaptor : public iterator_interface<IterConceptT, ElementT, RefT,
4246
if constexpr (std::copy_constructible<IteratorT> and std::copy_constructible<SentinelT>) {
4347
::new (destination) iterator_adaptor(*this);
4448
} else {
45-
std::unreachable();
49+
unreachable();
4650
}
4751
}
4852

@@ -51,15 +55,15 @@ class iterator_adaptor : public iterator_interface<IterConceptT, ElementT, RefT,
5155
std::is_nothrow_move_constructible_v<SentinelT>) {
5256
::new (destination) iterator_adaptor(std::move(*this));
5357
} else {
54-
std::unreachable();
58+
unreachable();
5559
}
5660
}
5761

5862
[[nodiscard]] constexpr auto copy() const -> iterator_adaptor* override {
5963
if constexpr (std::copy_constructible<IteratorT> and std::copy_constructible<SentinelT>) {
6064
return new iterator_adaptor(*this);
6165
} else {
62-
std::unreachable();
66+
unreachable();
6367
}
6468
}
6569

@@ -71,16 +75,16 @@ class iterator_adaptor : public iterator_interface<IterConceptT, ElementT, RefT,
7175
if constexpr (contiguous) {
7276
return std::to_address(iterator);
7377
} else {
74-
std::unreachable();
78+
unreachable();
7579
}
7680
}
7781

7882
constexpr auto operator++() -> void override { ++iterator; }
7983

8084
[[nodiscard]] constexpr auto operator==(const iterator_interface& other) const -> bool override {
8185
if constexpr (forward) {
82-
if (type() == other.type()) {
83-
return iterator == static_cast<const iterator_adaptor&>(other).iterator;
86+
if (const auto adaptor = down_cast(other)) {
87+
return iterator == adaptor->iterator;
8488
}
8589
}
8690

@@ -91,14 +95,14 @@ class iterator_adaptor : public iterator_interface<IterConceptT, ElementT, RefT,
9195
if constexpr (bidirectional) {
9296
--iterator;
9397
} else {
94-
std::unreachable();
98+
unreachable();
9599
}
96100
}
97101

98102
[[nodiscard]] constexpr auto operator<=>(const iterator_interface& other) const -> std::partial_ordering override {
99103
if constexpr (random_access) {
100-
if (type() == other.type()) {
101-
return iterator <=> static_cast<const iterator_adaptor&>(other).iterator;
104+
if (const auto adaptor = down_cast(other)) {
105+
return iterator <=> adaptor->iterator;
102106
}
103107
}
104108

@@ -107,29 +111,25 @@ class iterator_adaptor : public iterator_interface<IterConceptT, ElementT, RefT,
107111

108112
[[nodiscard]] constexpr auto operator-(const iterator_interface& other) const -> DiffT override {
109113
if constexpr (random_access) {
110-
if (type() == other.type()) {
111-
return iterator - static_cast<const iterator_adaptor&>(other).iterator;
114+
if (const auto adaptor = down_cast(other)) {
115+
return iterator - adaptor->iterator;
112116
}
113117
}
114118

115-
std::unreachable();
119+
unreachable();
116120
}
117121

118122
constexpr auto operator+=(DiffT offset) -> void override {
119123
if constexpr (random_access) {
120124
iterator += offset;
121125
} else {
122-
std::unreachable();
126+
unreachable();
123127
}
124128
}
125129

126130
[[nodiscard]] constexpr auto operator==(std::default_sentinel_t) const -> bool override {
127131
return iterator == sentinel;
128132
}
129-
130-
[[nodiscard]] constexpr auto type() const noexcept -> const std::type_info& override {
131-
return typeid(iterator_adaptor);
132-
}
133133
};
134134

135135
} // namespace beman::any_view::detail

include/beman/any_view/detail/iterator_interface.hpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
#include <compare>
77
#include <iterator>
88
#include <type_traits>
9-
#include <typeinfo>
109

1110
namespace beman::any_view::detail {
1211

@@ -44,9 +43,6 @@ class iterator_interface {
4443

4544
[[nodiscard]] virtual constexpr auto operator==(std::default_sentinel_t sentinel) const -> bool = 0;
4645

47-
// type query
48-
[[nodiscard]] virtual constexpr auto type() const noexcept -> const std::type_info& = 0;
49-
5046
virtual constexpr ~iterator_interface() noexcept = default;
5147
};
5248

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2+
3+
#ifndef BEMAN_ANY_VIEW_DETAIL_UTILITY_HPP
4+
#define BEMAN_ANY_VIEW_DETAIL_UTILITY_HPP
5+
6+
namespace beman::any_view::detail {
7+
8+
[[noreturn]] inline auto unreachable() -> void {
9+
#if defined(_MSC_VER)
10+
__assume(false);
11+
#elif defined(__GNUG__)
12+
__builtin_unreachable();
13+
#endif
14+
}
15+
16+
} // namespace beman::any_view::detail
17+
18+
#endif // BEMAN_ANY_VIEW_DETAIL_UTILITY_HPP

include/beman/any_view/detail/view_adaptor.hpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
#define BEMAN_ANY_VIEW_DETAIL_VIEW_ADAPTOR_HPP
55

66
#include <beman/any_view/detail/concepts.hpp>
7+
#include <beman/any_view/detail/utility.hpp>
78
#include <beman/any_view/detail/view_interface.hpp>
89

910
#include <ranges>
10-
#include <utility>
1111

1212
namespace beman::any_view::detail {
1313

@@ -27,31 +27,31 @@ class view_adaptor : public view_interface<IterConceptT, ElementT, RefT, RValueR
2727
if constexpr (std::copy_constructible<ViewT>) {
2828
::new (destination) view_adaptor(*this);
2929
} else {
30-
std::unreachable();
30+
unreachable();
3131
}
3232
}
3333

3434
auto move_to(void* destination) noexcept -> void override {
3535
if constexpr (std::is_nothrow_move_constructible_v<ViewT>) {
3636
::new (destination) view_adaptor(std::move(*this));
3737
} else {
38-
std::unreachable();
38+
unreachable();
3939
}
4040
}
4141

4242
[[nodiscard]] constexpr auto copy() const -> view_adaptor* override {
4343
if constexpr (std::copy_constructible<ViewT>) {
4444
return new view_adaptor(*this);
4545
} else {
46-
std::unreachable();
46+
unreachable();
4747
}
4848
}
4949

5050
[[nodiscard]] constexpr auto begin() -> iterator override {
5151
if constexpr (contiguous_reference_convertible_to<std::ranges::range_reference_t<ViewT>, RefT, IterConceptT>) {
5252
return iterator{std::ranges::begin(view), std::ranges::end(view)};
5353
} else {
54-
std::unreachable();
54+
unreachable();
5555
}
5656
}
5757

@@ -64,14 +64,14 @@ class view_adaptor : public view_interface<IterConceptT, ElementT, RefT, RValueR
6464
}
6565
}
6666

67-
std::unreachable();
67+
unreachable();
6868
}
6969

7070
[[nodiscard]] constexpr auto size() const -> size_type override {
7171
if constexpr (std::ranges::sized_range<ViewT>) {
7272
return std::ranges::size(view);
7373
} else {
74-
std::unreachable();
74+
unreachable();
7575
}
7676
}
7777
};

0 commit comments

Comments
 (0)