Skip to content

Commit

Permalink
Add virtual polymorphic view and iterator classes
Browse files Browse the repository at this point in the history
  • Loading branch information
patrickroberts committed Feb 7, 2025
1 parent 27128d7 commit 801a056
Show file tree
Hide file tree
Showing 11 changed files with 626 additions and 106 deletions.
8 changes: 2 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,8 @@ 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)
target_compile_features(beman.any_view INTERFACE cxx_std_20)
# TODO: implement non-template friend function and remove this suppression
target_compile_options(
beman.any_view
INTERFACE $<$<CXX_COMPILER_ID:GNU>:-Wno-non-template-friend>
)
# TODO: discuss removal of std::unreachable() to revert to C++20
target_compile_features(beman.any_view INTERFACE cxx_std_23)
target_include_directories(
beman.any_view
INTERFACE
Expand Down
1 change: 0 additions & 1 deletion CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"CMAKE_CXX_STANDARD": "20",
"CMAKE_EXPORT_COMPILE_COMMANDS": true
}
},
Expand Down
106 changes: 94 additions & 12 deletions include/beman/any_view/any_view.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@

#include <beman/any_view/concepts.hpp>
#include <beman/any_view/config.hpp>
#include <beman/any_view/detail/intrusive_small_ptr.hpp>
#include <beman/any_view/detail/iterator.hpp>
#include <beman/any_view/detail/view_adaptor.hpp>
#include <beman/any_view/detail/view_interface.hpp>

#if BEMAN_ANY_VIEW_USE_FLAGS()

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

using interface_type = detail::view_interface<iterator_concept, ElementT, RefT, RValueRefT, DiffT>;
// inplace storage sufficient for a vtable pointer and a std::vector<T>
detail::intrusive_small_ptr<interface_type, 4 * sizeof(void*)> view_ptr;

template <class RangeT>
using adaptor_type =
detail::view_adaptor<iterator_concept, ElementT, RefT, RValueRefT, DiffT, std::views::all_t<RangeT>>;

template <class RangeT>
static consteval auto get_in_place_adaptor_type() {
return std::in_place_type<adaptor_type<RangeT>>;
}

public:
template <detail::viewable_range_compatible_with<any_view> RangeT>
constexpr any_view(RangeT&&);
constexpr any_view(RangeT&& range)
: view_ptr(get_in_place_adaptor_type<RangeT>(), std::views::all(std::forward<RangeT>(range))) {}

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

[[nodiscard]] constexpr auto begin() -> iterator
requires(not simple);
requires(not simple)
{
return view_ptr->begin();
}

[[nodiscard]] constexpr auto begin() const -> iterator
requires simple;
requires simple
{
return view_ptr->begin();
}

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

[[nodiscard]] constexpr auto size() const -> size_type
requires sized;
requires sized
{
return view_ptr->size();
}
};

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

using interface_type =
detail::view_interface<iterator_concept, ElementT, reference_type, rvalue_reference_type, difference_type>;
// inplace storage sufficient for a vtable pointer and a std::vector<T>
detail::intrusive_small_ptr<interface_type, 4 * sizeof(void*)> view_ptr;

template <class RangeT>
using adaptor_type = detail::view_adaptor<iterator_concept,
ElementT,
reference_type,
rvalue_reference_type,
difference_type,
std::views::all_t<RangeT>>;

template <class RangeT>
static consteval auto get_in_place_adaptor_type() {
return std::in_place_type<adaptor_type<RangeT>>;
}

public:
template <detail::viewable_range_compatible_with<any_view> RangeT>
constexpr any_view(RangeT&&);
constexpr any_view(RangeT&& range)
: view_ptr(get_in_place_adaptor_type<RangeT>(), std::views::all(std::forward<RangeT>(range))) {}

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

[[nodiscard]] constexpr auto begin() -> iterator
requires(not simple);
requires(not simple)
{
return view_ptr->begin();
}

[[nodiscard]] constexpr auto begin() const -> iterator
requires simple;
requires simple
{
return view_ptr->begin();
}

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

[[nodiscard]] constexpr auto size() const -> size_type
requires sized;
requires sized
{
return view_ptr->size();
}
};

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

using interface_type =
detail::view_interface<iterator_concept, ElementT, reference_type, rvalue_reference_type, difference_type>;
// inplace storage sufficient for a vtable pointer and a std::vector<T>
detail::intrusive_small_ptr<interface_type, 4 * sizeof(void*)> view_ptr;

template <class RangeT>
using adaptor_type = detail::view_adaptor<iterator_concept,
ElementT,
reference_type,
rvalue_reference_type,
difference_type,
std::views::all_t<RangeT>>;

template <class RangeT>
static consteval auto get_in_place_adaptor_type() {
return std::in_place_type<adaptor_type<RangeT>>;
}

public:
template <detail::viewable_range_compatible_with<any_view> RangeT>
constexpr any_view(RangeT&&);
constexpr any_view(RangeT&& range)
: view_ptr(get_in_place_adaptor_type<RangeT>(), std::views::all(std::forward<RangeT>(range))) {}

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

[[nodiscard]] constexpr auto begin() -> iterator
requires(not simple);
requires(not simple)
{
return view_ptr->begin();
}

[[nodiscard]] constexpr auto begin() const -> iterator
requires simple;
requires simple
{
return view_ptr->begin();
}

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

[[nodiscard]] constexpr auto size() const -> size_type
requires sized;
requires sized
{
return view_ptr->size();
}
};

#endif
Expand Down
48 changes: 10 additions & 38 deletions include/beman/any_view/concepts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,20 @@
#ifndef BEMAN_ANY_VIEW_CONCEPTS_HPP
#define BEMAN_ANY_VIEW_CONCEPTS_HPP

#include <beman/any_view/detail/concepts.hpp>
#include <beman/any_view/range_traits.hpp>
#include <iterator>

namespace beman::any_view {
namespace detail {

template <class IterT, class IterConceptT>
concept input_iterator_compatible_with =
std::input_or_output_iterator<IterT> and
(not std::derived_from<IterConceptT, std::input_iterator_tag> or std::input_iterator<IterT>);

template <class IterT, class IterConceptT>
concept forward_iterator_compatible_with =
input_iterator_compatible_with<IterT, IterConceptT> and
(not std::derived_from<IterConceptT, std::forward_iterator_tag> or std::forward_iterator<IterT>);

template <class IterT, class IterConceptT>
concept bidirectional_iterator_compatible_with =
forward_iterator_compatible_with<IterT, IterConceptT> and
(not std::derived_from<IterConceptT, std::bidirectional_iterator_tag> or std::bidirectional_iterator<IterT>);

template <class IterT, class IterConceptT>
concept random_access_iterator_compatible_with =
bidirectional_iterator_compatible_with<IterT, IterConceptT> and
(not std::derived_from<IterConceptT, std::random_access_iterator_tag> or std::random_access_iterator<IterT>);

template <class IterT, class IterConceptT>
concept contiguous_iterator_compatible_with =
random_access_iterator_compatible_with<IterT, IterConceptT> and
(not std::derived_from<IterConceptT, std::contiguous_iterator_tag> or std::contiguous_iterator<IterT>);

template <class RangeRefT, class TraitsRefT, class IterConceptT>
concept contiguous_reference_convertible_to =
std::convertible_to<RangeRefT, TraitsRefT> and
(not std::derived_from<IterConceptT, std::contiguous_iterator_tag> or
std::convertible_to<std::remove_reference_t<RangeRefT> (*)[], std::remove_reference_t<TraitsRefT> (*)[]>);
template <class IteratorT, class RangeTraitsT>
concept iterator_compatible_with =
contiguous_iterator_compatible_with<IteratorT, iterator_concept_t<RangeTraitsT>> and
contiguous_reference_convertible_to<std::iter_reference_t<IteratorT>,
reference_type_t<RangeTraitsT>,
iterator_concept_t<RangeTraitsT>> and
std::convertible_to<std::iter_rvalue_reference_t<IteratorT>, rvalue_reference_type_t<RangeTraitsT>> and
std::convertible_to<std::iter_difference_t<IteratorT>, difference_type_t<RangeTraitsT>>;

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

template <class RangeT, class RangeTraitsT>
concept range_compatible_with =
std::ranges::range<RangeT> and
contiguous_iterator_compatible_with<std::ranges::iterator_t<RangeT>, iterator_concept_t<RangeTraitsT>> and
contiguous_reference_convertible_to<std::ranges::range_reference_t<RangeT>,
reference_type_t<RangeTraitsT>,
iterator_concept_t<RangeTraitsT>> and
std::convertible_to<std::ranges::range_rvalue_reference_t<RangeT>, rvalue_reference_type_t<RangeTraitsT>> and
std::convertible_to<std::ranges::range_difference_t<RangeT>, difference_type_t<RangeTraitsT>> and
std::ranges::range<RangeT> and iterator_compatible_with<std::ranges::iterator_t<RangeT>, RangeTraitsT> and
sized_range_compatible_with<RangeT, RangeTraitsT> and borrowed_range_compatible_with<RangeT, RangeTraitsT>;

template <class ViewT, class RangeTraitsT>
Expand Down
31 changes: 31 additions & 0 deletions include/beman/any_view/detail/concepts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,37 @@ concept simple_range = std::ranges::range<RangeT> and std::ranges::range<const R
std::same_as<std::ranges::iterator_t<RangeT>, std::ranges::iterator_t<const RangeT>> and
std::same_as<std::ranges::sentinel_t<RangeT>, std::ranges::sentinel_t<const RangeT>>;

template <class IterT, class IterConceptT>
concept input_iterator_compatible_with =
std::input_or_output_iterator<IterT> and
(not std::derived_from<IterConceptT, std::input_iterator_tag> or std::input_iterator<IterT>);

template <class IterT, class IterConceptT>
concept forward_iterator_compatible_with =
input_iterator_compatible_with<IterT, IterConceptT> and
(not std::derived_from<IterConceptT, std::forward_iterator_tag> or std::forward_iterator<IterT>);

template <class IterT, class IterConceptT>
concept bidirectional_iterator_compatible_with =
forward_iterator_compatible_with<IterT, IterConceptT> and
(not std::derived_from<IterConceptT, std::bidirectional_iterator_tag> or std::bidirectional_iterator<IterT>);

template <class IterT, class IterConceptT>
concept random_access_iterator_compatible_with =
bidirectional_iterator_compatible_with<IterT, IterConceptT> and
(not std::derived_from<IterConceptT, std::random_access_iterator_tag> or std::random_access_iterator<IterT>);

template <class IterT, class IterConceptT>
concept contiguous_iterator_compatible_with =
random_access_iterator_compatible_with<IterT, IterConceptT> and
(not std::derived_from<IterConceptT, std::contiguous_iterator_tag> or std::contiguous_iterator<IterT>);

template <class RangeRefT, class TraitsRefT, class IterConceptT>
concept contiguous_reference_convertible_to =
std::convertible_to<RangeRefT, TraitsRefT> and
(not std::derived_from<IterConceptT, std::contiguous_iterator_tag> or
std::convertible_to<std::remove_reference_t<RangeRefT> (*)[], std::remove_reference_t<TraitsRefT> (*)[]>);

} // namespace beman::any_view::detail

#endif // BEMAN_ANY_VIEW_DETAIL_CONCEPTS_HPP
Loading

0 comments on commit 801a056

Please sign in to comment.