Skip to content

Commit

Permalink
Use intrinsics for unreachable to support C++20
Browse files Browse the repository at this point in the history
  • Loading branch information
patrickroberts committed Feb 8, 2025
1 parent 3c614bb commit 75a090b
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 31 deletions.
3 changes: 1 addition & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@ include(GNUInstallDirs)
add_library(beman.any_view INTERFACE)
add_library(beman::any_view ALIAS beman.any_view)
set_target_properties(beman.any_view PROPERTIES CXX_EXTENSIONS OFF)
# TODO: discuss removal of std::unreachable() to revert to C++20
target_compile_features(beman.any_view INTERFACE cxx_std_23)
target_compile_features(beman.any_view INTERFACE cxx_std_20)
target_include_directories(
beman.any_view
INTERFACE
Expand Down
36 changes: 18 additions & 18 deletions include/beman/any_view/detail/iterator_adaptor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
#define BEMAN_ANY_VIEW_DETAIL_ITERATOR_ADAPTOR_HPP

#include <beman/any_view/detail/iterator_interface.hpp>
#include <beman/any_view/detail/utility.hpp>

#include <compare>
#include <iterator>
#include <utility>

namespace beman::any_view::detail {

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

static constexpr auto down_cast(const iterator_interface& other) {
return dynamic_cast<const iterator_adaptor*>(std::addressof(other));
}

public:
constexpr iterator_adaptor(IteratorT&& iterator, SentinelT&& sentinel) noexcept(get_noexcept())
: iterator(std::move(iterator)), sentinel(std::move(sentinel)) {}
Expand All @@ -42,7 +46,7 @@ class iterator_adaptor : public iterator_interface<IterConceptT, ElementT, RefT,
if constexpr (std::copy_constructible<IteratorT> and std::copy_constructible<SentinelT>) {
::new (destination) iterator_adaptor(*this);
} else {
std::unreachable();
unreachable();
}
}

Expand All @@ -51,15 +55,15 @@ class iterator_adaptor : public iterator_interface<IterConceptT, ElementT, RefT,
std::is_nothrow_move_constructible_v<SentinelT>) {
::new (destination) iterator_adaptor(std::move(*this));
} else {
std::unreachable();
unreachable();
}
}

[[nodiscard]] constexpr auto copy() const -> iterator_adaptor* override {
if constexpr (std::copy_constructible<IteratorT> and std::copy_constructible<SentinelT>) {
return new iterator_adaptor(*this);
} else {
std::unreachable();
unreachable();
}
}

Expand All @@ -71,16 +75,16 @@ class iterator_adaptor : public iterator_interface<IterConceptT, ElementT, RefT,
if constexpr (contiguous) {
return std::to_address(iterator);
} else {
std::unreachable();
unreachable();
}
}

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

[[nodiscard]] constexpr auto operator==(const iterator_interface& other) const -> bool override {
if constexpr (forward) {
if (type() == other.type()) {
return iterator == static_cast<const iterator_adaptor&>(other).iterator;
if (const auto adaptor = down_cast(other)) {
return iterator == adaptor->iterator;
}
}

Expand All @@ -91,14 +95,14 @@ class iterator_adaptor : public iterator_interface<IterConceptT, ElementT, RefT,
if constexpr (bidirectional) {
--iterator;
} else {
std::unreachable();
unreachable();
}
}

[[nodiscard]] constexpr auto operator<=>(const iterator_interface& other) const -> std::partial_ordering override {
if constexpr (random_access) {
if (type() == other.type()) {
return iterator <=> static_cast<const iterator_adaptor&>(other).iterator;
if (const auto adaptor = down_cast(other)) {
return iterator <=> adaptor->iterator;
}
}

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

[[nodiscard]] constexpr auto operator-(const iterator_interface& other) const -> DiffT override {
if constexpr (random_access) {
if (type() == other.type()) {
return iterator - static_cast<const iterator_adaptor&>(other).iterator;
if (const auto adaptor = down_cast(other)) {
return iterator - adaptor->iterator;
}
}

std::unreachable();
unreachable();
}

constexpr auto operator+=(DiffT offset) -> void override {
if constexpr (random_access) {
iterator += offset;
} else {
std::unreachable();
unreachable();
}
}

[[nodiscard]] constexpr auto operator==(std::default_sentinel_t) const -> bool override {
return iterator == sentinel;
}

[[nodiscard]] constexpr auto type() const noexcept -> const std::type_info& override {
return typeid(iterator_adaptor);
}
};

} // namespace beman::any_view::detail
Expand Down
4 changes: 0 additions & 4 deletions include/beman/any_view/detail/iterator_interface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#include <compare>
#include <iterator>
#include <type_traits>
#include <typeinfo>

namespace beman::any_view::detail {

Expand Down Expand Up @@ -44,9 +43,6 @@ class iterator_interface {

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

// type query
[[nodiscard]] virtual constexpr auto type() const noexcept -> const std::type_info& = 0;

virtual constexpr ~iterator_interface() noexcept = default;
};

Expand Down
18 changes: 18 additions & 0 deletions include/beman/any_view/detail/utility.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#ifndef BEMAN_ANY_VIEW_DETAIL_UTILITY_HPP
#define BEMAN_ANY_VIEW_DETAIL_UTILITY_HPP

namespace beman::any_view::detail {

[[noreturn]] inline auto unreachable() -> void {
#if defined(_MSC_VER)
__assume(false);
#elif defined(__GNUG__)
__builtin_unreachable();
#endif
}

} // namespace beman::any_view::detail

#endif // BEMAN_ANY_VIEW_DETAIL_UTILITY_HPP
14 changes: 7 additions & 7 deletions include/beman/any_view/detail/view_adaptor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
#define BEMAN_ANY_VIEW_DETAIL_VIEW_ADAPTOR_HPP

#include <beman/any_view/detail/concepts.hpp>
#include <beman/any_view/detail/utility.hpp>
#include <beman/any_view/detail/view_interface.hpp>

#include <ranges>
#include <utility>

namespace beman::any_view::detail {

Expand All @@ -27,31 +27,31 @@ class view_adaptor : public view_interface<IterConceptT, ElementT, RefT, RValueR
if constexpr (std::copy_constructible<ViewT>) {
::new (destination) view_adaptor(*this);
} else {
std::unreachable();
unreachable();
}
}

auto move_to(void* destination) noexcept -> void override {
if constexpr (std::is_nothrow_move_constructible_v<ViewT>) {
::new (destination) view_adaptor(std::move(*this));
} else {
std::unreachable();
unreachable();
}
}

[[nodiscard]] constexpr auto copy() const -> view_adaptor* override {
if constexpr (std::copy_constructible<ViewT>) {
return new view_adaptor(*this);
} else {
std::unreachable();
unreachable();
}
}

[[nodiscard]] constexpr auto begin() -> iterator override {
if constexpr (contiguous_reference_convertible_to<std::ranges::range_reference_t<ViewT>, RefT, IterConceptT>) {
return iterator{std::ranges::begin(view), std::ranges::end(view)};
} else {
std::unreachable();
unreachable();
}
}

Expand All @@ -64,14 +64,14 @@ class view_adaptor : public view_interface<IterConceptT, ElementT, RefT, RValueR
}
}

std::unreachable();
unreachable();
}

[[nodiscard]] constexpr auto size() const -> size_type override {
if constexpr (std::ranges::sized_range<ViewT>) {
return std::ranges::size(view);
} else {
std::unreachable();
unreachable();
}
}
};
Expand Down

0 comments on commit 75a090b

Please sign in to comment.