VCCC  2024.05
VisualCamp Common C++ library
range_adaptor_closure.hpp
Go to the documentation of this file.
1 //
2 // Created by yonggyulee on 2023/01/01.
3 //
4 
5 #ifndef VCCC_RANGES_RANGE_ADAPTOR_CLOSURE_HPP
6 #define VCCC_RANGES_RANGE_ADAPTOR_CLOSURE_HPP
7 
8 #include <cstddef>
9 #include <type_traits>
10 
14 #include "vccc/__ranges/range.hpp"
20 
21 namespace vccc {
22 namespace ranges {
23 
24 template<typename Derived>
25 struct range_adaptor_closure;
26 
27 namespace detail {
28 
29 struct basic_range {
30  constexpr basic_range() noexcept : data_(0) {}
31 
32  constexpr unsigned char* begin() noexcept { return &data_; }
33  constexpr const unsigned char* begin() const noexcept { return &data_; }
34  constexpr unsigned char* end() noexcept { return &data_ + 1; }
35  constexpr const unsigned char* end() const noexcept { return &data_ + 1; }
36  constexpr std::size_t size() const noexcept { return 1; }
37 
38  unsigned char data_;
39 };
40 
41 template<typename C, typename D>
42 class range_adaptor_closure_object
43  : protected compressed_pair<C, D>
44  , public range_adaptor_closure<range_adaptor_closure_object<C, D>>
45 {
46  using pair_base = compressed_pair<C, D>;
47 
48  public:
49  constexpr range_adaptor_closure_object() = default;
50 
51  template<typename T, typename U, std::enable_if_t<conjunction<
52  std::is_constructible<C, T>, std::is_constructible<D, U>
53  >::value, int> = 0>
54  constexpr range_adaptor_closure_object(T&& t, U&& u)
55  noexcept(conjunction<std::is_nothrow_constructible<C, T>, std::is_nothrow_constructible<D, U>>::value)
56  : pair_base(std::forward<T>(t), std::forward<U>(u)) {}
57 
58  template<typename... Args, std::enable_if_t<is_invocable<C, Args&&...>::value, int> = 0>
59  constexpr invoke_result_t<D, invoke_result_t<C, Args&&...>>
60  operator()(Args&&... args) const
61  noexcept(conjunction<is_nothrow_invocable<C, Args&&...>,
62  is_nothrow_invocable<D, invoke_result_t<C, Args&&...>> >::value)
63  {
64  return vccc::invoke(pair_base::second(), vccc::invoke(pair_base::first(), std::forward<Args>(args)...));
65  }
66 
67 };
68 
69 template<typename C, typename D>
70 using range_adaptor_closure_object_t = range_adaptor_closure_object<std::remove_reference_t<C>, std::remove_reference_t<D>>;
71 
72 } // namespace detail
73 
76 
78 template<typename T>
80  : conjunction<
81  derived_from_single_crtp<T, range_adaptor_closure>,
82  is_invocable<T, detail::basic_range>,
83  negation< range<T> >
84  > {};
85 
95 template<typename Derived>
97  static_assert(std::is_object<Derived>::value, "Constraints not satisfied");
98  static_assert(same_as<Derived, std::remove_cv_t<Derived>>::value, "Constraints not satisfied");
99 
100  template<typename Range, typename This, std::enable_if_t<conjunction<
103  >::value, int> = 0>
104  friend constexpr invoke_result_t<This, Range>
105  operator|(Range&& r, This&& c)
107  {
108  return vccc::invoke(std::forward<This>(c), std::forward<Range>(r));
109  }
110 
111  template<typename This, typename Closure, std::enable_if_t<conjunction<
115  std::is_constructible<detail::range_adaptor_closure_object_t<This, Closure>, This, Closure>
116  >::value, int> = 0>
117  friend constexpr detail::range_adaptor_closure_object_t<This, Closure>
118  operator|(This&& c1, Closure&& c2)
119  noexcept(std::is_nothrow_constructible<detail::range_adaptor_closure_object_t<This, Closure>, This, Closure>::value)
120  {
121  return detail::range_adaptor_closure_object_t<This, Closure>(std::forward<This>(c1), std::forward<Closure>(c2));
122  }
123 };
124 
126 
127 } // namespace ranges
128 } // namespace vccc
129 
130 #endif // VCCC_RANGES_RANGE_ADAPTOR_CLOSURE_HPP
constexpr C & first() &noexcept
Definition: compressed_pair.hpp:85
constexpr D & second() &noexcept
Definition: compressed_pair.hpp:90
constexpr invoke_result_t< F, Args... > invoke(F &&f, Args &&... args) noexcept(is_nothrow_invocable< F, Args... >::value)
Definition: invoke.hpp:38
constexpr VCCC_INLINE_OR_STATIC detail::begin_niebloid begin
returns an iterator to the beginning of a range
Definition: begin.hpp:116
constexpr VCCC_INLINE_OR_STATIC detail::end_niebloid end
returns a sentinel indicating the end of a range
Definition: end.hpp:120
typename invoke_result< F, Args... >::type invoke_result_t
Definition: is_invocable.hpp:66
Definition: matrix.hpp:495
Definition: directory.h:12
constexpr auto size(const C &c) -> decltype(c.size())
Definition: size.hpp:16
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 1 > value
Definition: key_value.hpp:35
Definition: conjunction.hpp:22
Determines whether INVOKE(std::declval<Fn>(), std::declval<ArgTypes>()...) is well formed when treate...
Definition: is_invocable.hpp:91
check if type satisfies range adaptor closure object
Definition: range_adaptor_closure.hpp:84
helper base class template for defining a range adaptor closure object
Definition: range_adaptor_closure.hpp:96
constexpr friend invoke_result_t< This, Range > operator|(Range &&r, This &&c) noexcept(is_nothrow_invocable< This, Range >::value)
Definition: range_adaptor_closure.hpp:105
constexpr friend detail::range_adaptor_closure_object_t< This, Closure > operator|(This &&c1, Closure &&c2) noexcept(std::is_nothrow_constructible< detail::range_adaptor_closure_object_t< This, Closure >, This, Closure >::value)
Definition: range_adaptor_closure.hpp:118
specifies that a type is a range, that is, it provides a begin iterator and an end sentinel
Definition: range.hpp:53
Models std::same_as
Definition: same_as.hpp:33