Skip to content

Commit

Permalink
Fix n refactor (#40)
Browse files Browse the repository at this point in the history
* Fix forward_like

* Update override_cvref.h

* Fix typo

* Fix typo :(

* Update ref_view.h

* Fix as_const_view::as_const_view()

* Fix drop_view handling repeat_view

* Fix drop_view::drop_view

* Fix enumerate_view::enumerate_view

* Fix filter_view:: filter_view

* Fix iota_view::end() for unreachble_sentinel

* Fix join_with_view::join_with_view

* Fix views::repeat using remove_cvref_t instead of decay_t

* Fix missing constraints on repeat_view::repeat_view(const W&)

* Fix missing constraints for single_view

* Optimize views::take handling repeat_view

* Fix views::take_while using remove_cvref_t instead of decay_t

* Update zip_transform.h

* Rollback to good-old Dummy-void constraints

* Update range_adaptor.h

* Hide drop_while_view::cached_begin

* Fix lazy_split_view

* Update split_view.h
  • Loading branch information
lackhole committed Aug 23, 2024
1 parent 969bd15 commit 6b9405f
Show file tree
Hide file tree
Showing 26 changed files with 542 additions and 353 deletions.
2 changes: 1 addition & 1 deletion include/preview/__concepts/derived_from_single_crtp.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ template<
bool = is_referencable<Derived>::value /* true */
>
struct derived_from_single_crtp_impl
#if defined(_MSC_VER) && _MSC_VER < 1930 // Ambigious casting is allowed until Visutal Studio 2022
#if defined(_MSC_VER) && _MSC_VER < 1930 // Ambiguous casting is allowed until Visual Studio 2022
: has_typename_preview_derived<Derived> {};
#else
: is_invocable_r<
Expand Down
2 changes: 1 addition & 1 deletion include/preview/__functional/bind_partial.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class bind_partial {
std::is_constructible<BoundArgs, Args>...
>::value, int> = 0>
constexpr explicit bind_partial(F&& f, Args&&... args)
: pair_(std::piecewise_construct, std::forward_as_tuple(std::forward<F>(f)), std::forward_as_tuple(std::forward<Args>(args))...) {}
: pair_(std::piecewise_construct, std::forward_as_tuple(std::forward<F>(f)), std::forward_as_tuple(std::forward<Args>(args)...)) {}

template<typename... CallArgs, std::enable_if_t<bind_invocable<Derived&, CallArgs&&...>::value, int> = 0>
constexpr decltype(auto) operator()(CallArgs&&... call_args) &
Expand Down
14 changes: 7 additions & 7 deletions include/preview/__ranges/range_adaptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,28 +34,28 @@ class range_adaptor : public range_adaptor_closure<range_adaptor<Niebloid, Args.

template<typename R, std::enable_if_t<is_invocable<Niebloid, R, Args&...>::value, int> = 0>
constexpr decltype(auto) operator()(R&& r) & {
return call(*this, std::forward<R>(r), std::index_sequence_for<Args...>{});
return call(std::forward<R>(r), args_, std::index_sequence_for<Args...>{});
}

template<typename R, std::enable_if_t<is_invocable<Niebloid, R, const Args&...>::value, int> = 0>
constexpr decltype(auto) operator()(R&& r) const & {
return call(*this, std::forward<R>(r), std::index_sequence_for<Args...>{});
return call(std::forward<R>(r), args_, std::index_sequence_for<Args...>{});
}

template<typename R, std::enable_if_t<is_invocable<Niebloid, R, Args&&...>::value, int> = 0>
constexpr decltype(auto) operator()(R&& r) && {
return call(std::move(*this), std::forward<R>(r), std::index_sequence_for<Args...>{});
return call(std::forward<R>(r), std::move(args_), std::index_sequence_for<Args...>{});
}

template<typename R, std::enable_if_t<is_invocable<Niebloid, R, const Args&&...>::value, int> = 0>
constexpr decltype(auto) operator()(R&& r) const && {
return call(std::move(*this), std::forward<R>(r), std::index_sequence_for<Args...>{});
return call(std::forward<R>(r), std::move(args_), std::index_sequence_for<Args...>{});
}

private:
template<typename This, typename R, std::size_t... I>
static constexpr decltype(auto) call(This&& thiz, R&& r, std::index_sequence<I...>) {
return Niebloid{}(std::forward<R>(r), std::get<I>(std::forward<This>(thiz).args_)...);
template<typename ArgTuple, typename R, std::size_t... I>
static constexpr decltype(auto) call(R&& r, ArgTuple&& tuple, std::index_sequence<I...>) {
return Niebloid{}(std::forward<R>(r), std::get<I>(std::forward<ArgTuple>(tuple))...);
}

std::tuple<Args...> args_;
Expand Down
16 changes: 15 additions & 1 deletion include/preview/__ranges/ref_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,30 @@

namespace preview {
namespace ranges {
namespace detail {
namespace ref_view_fn {

template<typename R> static void fun(R&);
template<typename R> static void fun(R&&) = delete;

template<typename R, typename T, typename = void>
struct fallback_to_lref : std::false_type {};
template<typename R, typename T>
struct fallback_to_lref<R, T, void_t<decltype(fun<R>(std::declval<T>()))>> : std::true_type {};

} // namespace ref_view_fn
} // namespace detail

template<typename R>
class ref_view : public view_interface<ref_view<R>> {
public:
static_assert(range<R>::value, "Constraints not satisfied");
static_assert(std::is_object<R>::value, "Constraints not satisfied");

template<typename T, std::enable_if_t<conjunction<
different_from<T, ref_view>,
convertible_to<T, R&>,
std::is_lvalue_reference<T&&>
detail::ref_view_fn::fallback_to_lref<R, T>
>::value, int> = 0>
PREVIEW_CONSTEXPR_AFTER_CXX17 ref_view(T&& t) noexcept
: r_(preview::addressof(static_cast<R&>(std::forward<T>(t)))) {}
Expand Down
2 changes: 1 addition & 1 deletion include/preview/__ranges/views/as_const_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class as_const_view : public view_interface<as_const_view<V>> {
}

private:
V base_;
V base_{};
};

#if __cplusplus >= 201703L
Expand Down
159 changes: 66 additions & 93 deletions include/preview/__ranges/views/drop.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
#if PREVIEW_CXX_VERSION >= 17
#include <string_view>
#endif
#if PREVIEW_CXX_VERSION >= 20
#include <span>
#endif

#include "preview/__concepts/different_from.h"
#include "preview/__ranges/range.h"
Expand All @@ -31,6 +34,7 @@
#include "preview/__type_traits/detail/return_category.h"
#include "preview/__type_traits/is_specialization.h"
#include "preview/__type_traits/remove_cvref.h"
#include "preview/__utility/forward_like.h"
#include "preview/__utility/to_unsigned_like.h"

namespace preview {
Expand All @@ -42,144 +46,113 @@ using preview::detail::return_category;

struct drop_niebloid {
private:
// empty_view - 1
template<typename R, typename T, typename D, bool = is_specialization<T, empty_view>::value /* true */>
struct return_category_empty_view : std::true_type {
using category = return_category<1, decltype(preview_decay_copy(std::declval<R>()))>;
};
template<typename R, typename T, typename D>
struct return_category_empty_view<R, T, D, false> : std::false_type {
using category = return_category<0>;
};
template<typename R, typename D, typename RT>
constexpr RT operator()(R&& r, D, return_category<1, RT>) const {
return std::forward<R>(r);
}

// subrange - 2 / 3
// subrange
template<typename T, bool = conjunction<ranges::detail::is_subrange<T>, random_access_range<T>, sized_range<T>>::value /* true */>
struct return_category_subrange : std::true_type {
using category = std::conditional_t<ranges::detail::is_size_storing_subrange<T>::value,
return_category<2, T>,
return_category<3, T>
return_category<3, T>,
return_category<2, T>
>;
};
template<typename T>
struct return_category_subrange<T, false> : std::false_type {
using category = return_category<0>;
};

template<typename R, typename D, typename T>
constexpr T operator()(R&& e, D f, return_category<2, T>) const {
auto inc = (std::min<D>)(ranges::distance(e), f);
return T(
ranges::begin(e) + inc,
ranges::end(e),
preview::to_unsigned_like(ranges::distance(e) - inc)
);
}

// span - 3
// span
template<typename T>
struct is_span : std::false_type {};
struct return_category_span : std::false_type {
using category = return_category<0>;
};
template<typename T, std::size_t Extent>
struct is_span<span<T, Extent>> : std::true_type {};

template<typename T, typename D, bool = is_span<T>::value /* true */>
struct return_category_span : std::true_type {
using category = return_category<3, span<typename T::element_type>>;
struct return_category_span<span<T, Extent>> : std::true_type {
using category = return_category<2, span<T>>;
};
template<typename T, typename D>
struct return_category_span<T, D, false> : std::false_type {
using category = return_category<0>;
#if PREVIEW_CXX_VERSION >= 20
template<typename T, std::size_t Extent>
struct return_category_span<std::span<T, Extent>> : std::true_type {
using category = return_category<2, std::span<T>>;
};
#endif

// basic_string_view - 3
template<typename T, bool = disjunction<
template<typename T>
using is_basic_string_view = disjunction<
is_specialization<T, basic_string_view>
#if PREVIEW_CXX_VERSION >= 17
, is_specialization<T, std::basic_string_view>
#endif
>::value /* true */>
struct return_category_string_view : std::true_type {
using category = return_category<3, T>;
};
template<typename T>
struct return_category_string_view<T, false> : std::false_type {
using category = return_category<0>;
};
>;

// iota_view - 3
template<typename T, bool = conjunction<
is_specialization<T, iota_view>,
sized_range<T>,
random_access_range<T>
>::value /* true */>
struct return_category_iota_view : std::true_type {
using category = return_category<3, T>;
};
template<typename T>
struct return_category_iota_view<T, false> : std::false_type {
using category = return_category<0>;
};
// 2.1 empty_view
template<typename R, typename D>
constexpr auto call(R&& r, D, return_category<1>) const {
return preview_decay_copy(std::forward<R>(r));
}

// TODO: Investigate for subrange fallback
// 2.2 span, basic_string_view, iota_view, subrange (StoreSize == false)
template<typename R, typename D, typename U>
constexpr U operator()(R&& e, D f, return_category<3, U>) const {
constexpr U call(R&& e, D f, return_category<2, U>) const {
return U(
ranges::begin(e) + (std::min<D>)(ranges::distance(e), f),
ranges::end(e)
);
}

// repeat_view - 4
template<typename T, bool = is_specialization<T, repeat_view>::value /* false */>
struct return_category_repeat_view : std::false_type {
using category = return_category<0>;
};
template<typename T>
struct return_category_repeat_view<T, true> : std::true_type {
using category = return_category<4, bool_constant<sized_range<T>::value>>;
};
// 2.3 subrange
template<typename R, typename D, typename T>
constexpr T call(R&& e, D f, return_category<3, T>) const {
auto inc = (std::min<D>)(ranges::distance(e), f);
return T(
ranges::begin(e) + inc,
ranges::end(e),
preview::to_unsigned_like(ranges::distance(e) - inc)
);
}

// 2.4. repeat_view
template<typename R, typename D>
constexpr auto operator()(R&& e, D f, return_category<4, std::true_type /* sized_range */>) const {
return views::repeat(*e, ranges::distance(e) - (std::min<D>)(ranges::distance(e), f));
constexpr auto call(R&& e, D f, return_category<4, std::true_type /* sized_range */>) const {
return views::repeat(
preview::force_forward_like<R>(*e.begin()), // *e.value_
ranges::distance(e) - (std::min<D>)(ranges::distance(e), f)
);
}
template<typename R, typename D>
constexpr auto operator()(R&& e, D, return_category<4, std::false_type /* sized_range */>) const {
return preview_decay_copy(e);
constexpr auto call(R&& e, D f, return_category<4, std::false_type /* sized_range */>) const {
return ((void)f, preview_decay_copy(e));
}

// drop_view - 0 (default)
// 2.5 drop_view
template<typename R, typename D>
constexpr drop_view<all_t<R>> operator()(R&& r, D f, return_category<0>) const {
constexpr drop_view<all_t<R>> call(R&& r, D f, return_category<5>) const {
return drop_view<all_t<R>>(std::forward<R>(r), f);
}

template<typename R, typename T, typename D>
using category =
conditional_t<
return_category_empty_view<R, T, D>, typename return_category_empty_view<R, T, D>::category, // 1
return_category_span<T, D>, typename return_category_span<T, D>::category, // 3
return_category_string_view<T>, typename return_category_string_view<T>::category, // 3
return_category_subrange<T>, typename return_category_subrange<T>::category, // 2 or 3
return_category_iota_view<T>, typename return_category_iota_view<T>::category, // 3
return_category_repeat_view<T>, typename return_category_iota_view<T>::category, // 4
return_category<0>
>;
template<typename T>
using category = conditional_t<
is_specialization<T, empty_view>, return_category<1>,
return_category_span<T>, typename return_category_span<T>::category, // 2
is_basic_string_view<T>, return_category<2, T>,
conjunction<
is_specialization<T, iota_view>,
sized_range<T>,
random_access_range<T>
>, return_category<2, T>,
return_category_subrange<T>, typename return_category_subrange<T>::category, // 2 or 3
is_specialization<T, repeat_view>, return_category<4, bool_constant<sized_range<T>::value>>,
return_category<5>
>;

public:
template<typename R, std::enable_if_t<viewable_range<R>::value, int> = 0>
constexpr auto
operator()(R&& r, range_difference_t<R> count) const {
constexpr auto operator()(R&& r, range_difference_t<R> count) const {
using T = remove_cvref_t<decltype((r))>;
using D = range_difference_t<decltype((r))>;
return (*this)(std::forward<R>(r), count, category<R&&, T, D>{});
return call(std::forward<R>(r), std::move(count), category<T>{});
}

template<typename DifferenceType>
constexpr auto operator()(DifferenceType&& count) const {
return range_adaptor<drop_niebloid, std::remove_reference_t<DifferenceType>>(std::forward<DifferenceType>(count));
return range_adaptor<drop_niebloid, std::decay_t<DifferenceType>>(std::forward<DifferenceType>(count));
}
};

Expand Down
2 changes: 1 addition & 1 deletion include/preview/__ranges/views/drop_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ class drop_view : public detail::drop_view_cached_begin<drop_view<V>, V> {
}

private:
V base_;
V base_{};
range_difference_t<V> count_ = 0;
};

Expand Down
7 changes: 4 additions & 3 deletions include/preview/__ranges/views/drop_while_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ namespace detail {
template<typename DropWhileView, typename V, bool Cached = forward_range<V>::value/* true */>
struct drop_while_view_cached_begin : public view_interface<DropWhileView> {
template<typename Base, typename Pred>
constexpr auto begin(Base& base, Pred& pred) {
constexpr auto begin_impl(Base& base, Pred& pred) {
if (!cached_begin_.has_value()) {
cached_begin_.emplace(ranges::find_if_not(base, std::cref(*pred)));
}
Expand All @@ -44,7 +44,7 @@ struct drop_while_view_cached_begin : public view_interface<DropWhileView> {
template<typename DropWhileView, typename V>
struct drop_while_view_cached_begin<DropWhileView, V, false> : public view_interface<DropWhileView> {
template<typename Base, typename Pred>
constexpr auto begin(Base& base, Pred& pred) {
constexpr auto begin_impl(Base& base, Pred& pred) {
return ranges::find_if_not(base, std::cref(*pred));
}
};
Expand All @@ -56,6 +56,7 @@ class drop_while_view
: public detail::drop_while_view_cached_begin<drop_while_view<V, Pred>, V>
{
using begin_base = detail::drop_while_view_cached_begin<drop_while_view<V, Pred>, V>;
using begin_base::begin_impl;

public:
static_assert(view<V>::value, "Constraints not satisfied");
Expand Down Expand Up @@ -84,7 +85,7 @@ class drop_while_view
}

constexpr auto begin() {
return begin_base::begin(base_, pred_);
return begin_base::begin_impl(base_, pred_);
}

constexpr auto end() {
Expand Down
2 changes: 1 addition & 1 deletion include/preview/__ranges/views/enumerate_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ class enumerate_view : public view_interface<enumerate_view<V>> {
return sentinel<true>(ranges::end(base_));
}

V base_;
V base_{};
};

#if __cplusplus >= 201703L
Expand Down
Loading

0 comments on commit 6b9405f

Please sign in to comment.