Horizon
memory.hpp
Go to the documentation of this file.
1 // Range v3 library
3 //
4 // Copyright Eric Niebler 2014-present
5 //
6 // Use, modification and distribution is subject to the
7 // Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10 //
11 // Project home: https://github.com/ericniebler/range-v3
12 //
13 //===-------------------------- algorithm ---------------------------------===//
14 //
15 // The LLVM Compiler Infrastructure
16 //
17 // This file is dual licensed under the MIT and the University of Illinois Open
18 // Source Licenses. See LICENSE.TXT for details.
19 //
20 //===----------------------------------------------------------------------===//
21 #ifndef RANGES_V3_UTILITY_MEMORY_HPP
22 #define RANGES_V3_UTILITY_MEMORY_HPP
23 
24 #include <cstdint>
25 #include <memory>
26 #include <type_traits>
27 #include <utility>
28 
29 #include <meta/meta.hpp>
30 
31 #include <range/v3/detail/config.hpp>
34 #include <range/v3/utility/polymorphic_cast.hpp>
35 
36 #include <range/v3/detail/prologue.hpp>
37 
38 namespace ranges
39 {
41  namespace detail
42  {
43  template<typename T>
44  std::pair<T *, std::ptrdiff_t> get_temporary_buffer_impl(std::size_t n) noexcept
45  {
46  if(n > PTRDIFF_MAX / sizeof(T))
47  n = PTRDIFF_MAX / sizeof(T);
48 
49  void * ptr = nullptr;
50  for(; ptr == nullptr && n > 0; n /= 2)
51  {
52 #if RANGES_CXX_ALIGNED_NEW < RANGES_CXX_ALIGNED_NEW_17
53  static_assert(alignof(T) <= alignof(std::max_align_t),
54  "Sorry: over-aligned types are supported only with C++17.");
55 #else // RANGES_CXX_ALIGNED_NEW
56  if(RANGES_CONSTEXPR_IF(alignof(T) > __STDCPP_DEFAULT_NEW_ALIGNMENT__))
57  ptr = ::operator new(
58  sizeof(T) * n, std::align_val_t{alignof(T)}, std::nothrow);
59  else
60 #endif // RANGES_CXX_ALIGNED_NEW
61  ptr = ::operator new(sizeof(T) * n, std::nothrow);
62  }
63 
64  return {static_cast<T *>(ptr), static_cast<std::ptrdiff_t>(n)};
65  }
66 
67  template<typename T, typename D>
68  std::pair<T *, std::ptrdiff_t> get_temporary_buffer(D count) noexcept
69  {
70  RANGES_EXPECT(count >= 0);
71  return detail::get_temporary_buffer_impl<T>(static_cast<std::size_t>(count));
72  }
73 
74  struct return_temporary_buffer
75  {
76  template<typename T>
77  void operator()(T * p) const
78  {
79 #if RANGES_CXX_ALIGNED_NEW < RANGES_CXX_ALIGNED_NEW_17
80  static_assert(alignof(T) <= alignof(std::max_align_t),
81  "Sorry: over-aligned types are supported only with C++17.");
82 #else // RANGES_CXX_ALIGNED_NEW
83  if(RANGES_CONSTEXPR_IF(alignof(T) > __STDCPP_DEFAULT_NEW_ALIGNMENT__))
84  ::operator delete(p, std::align_val_t{alignof(T)});
85  else
86 #endif // RANGES_CXX_ALIGNED_NEW
87  ::operator delete(p);
88  }
89  };
90 
91  template(typename T, typename... Args)(
92  requires (!std::is_array<T>::value)) //
93  std::unique_ptr<T> make_unique(Args &&... args)
94  {
95  return std::unique_ptr<T>{new T(static_cast<Args &&>(args)...)};
96  }
97  } // namespace detail
99 
102  template<typename O, typename Val>
104  {
105  private:
106  CPP_assert(output_iterator<O, Val>);
107  CPP_assert(std::is_lvalue_reference<iter_reference_t<O>>());
108  O out_;
109 
110  public:
111  using difference_type = iter_difference_t<O>;
112  raw_storage_iterator() = default;
113  explicit raw_storage_iterator(O out)
114  : out_(std::move(out))
115  {}
116  raw_storage_iterator & operator*() noexcept
117  {
118  return *this;
119  }
120  CPP_member
121  auto operator=(Val const & val) //
122  -> CPP_ret(raw_storage_iterator &)(
123  requires copy_constructible<Val>)
124  {
125  ::new((void *)std::addressof(*out_)) Val(val);
126  return *this;
127  }
128  CPP_member
129  auto operator=(Val && val) //
130  -> CPP_ret(raw_storage_iterator &)(
131  requires move_constructible<Val>)
132  {
133  ::new((void *)std::addressof(*out_)) Val(std::move(val));
134  return *this;
135  }
136  raw_storage_iterator & operator++()
137  {
138  ++out_;
139  return *this;
140  }
141  CPP_member
142  auto operator++(int) //
143  -> CPP_ret(void)(
144  requires (!forward_iterator<O>))
145  {
146  ++out_;
147  }
148  CPP_member
149  auto operator++(int) //
150  -> CPP_ret(raw_storage_iterator)(
151  requires forward_iterator<O>)
152  {
153  auto tmp = *this;
154  ++out_;
155  return tmp;
156  }
157  O base() const
158  {
159  return out_;
160  }
161  };
162 
163  template<typename I>
165  {
166  private:
167  CPP_assert(input_or_output_iterator<I>);
168  mutable I * i_ = nullptr;
169 
170  public:
171  using difference_type = iter_difference_t<I>;
172  iterator_wrapper() = default;
173  iterator_wrapper(iterator_wrapper const & that)
174  : i_(that.i_)
175  {
176  that.i_ = nullptr;
177  }
178  iterator_wrapper & operator=(iterator_wrapper const & that)
179  {
180  i_ = that.i_;
181  that.i_ = nullptr;
182  return *this;
183  }
184  iterator_wrapper(I & i)
185  : i_(std::addressof(i))
186  {}
187  // clang-format off
188  auto CPP_auto_fun(operator*)()(const)
189  (
190  return **i_
191  )
192  // clang-format on
194  operator++()
195  {
196  ++*i_;
197  return *this;
198  }
199  void operator++(int)
200  {
201  ++*i_;
202  }
203  I base() const
204  {
205  return *i_;
206  }
207  };
208 
209  template(typename I)(
210  requires input_or_output_iterator<I>)
211  iterator_wrapper<I> iter_ref(I & i)
212  {
213  return i;
214  }
215 
216  template<typename I>
218  : meta::if_c<(bool)input_iterator<I>, indirectly_readable_traits<I>, meta::nil_>
219  {};
220 
221  template<typename Val>
222  struct raw_buffer
223  {
224  private:
225  Val * begin_;
227 
228  public:
229  explicit raw_buffer(Val * first)
230  : begin_(first)
231  , rsi_(first)
232  {}
233  raw_buffer(raw_buffer &&) = default;
234  raw_buffer(raw_buffer const &) = delete;
235  ~raw_buffer()
236  {
237  for(; begin_ != rsi_.base(); ++begin_)
238  begin_->~Val();
239  }
241  {
242  return ranges::iter_ref(rsi_);
243  }
244  };
245 
246  template<typename Val>
247  raw_buffer<Val> make_raw_buffer(Val * val)
248  {
249  return raw_buffer<Val>(val);
250  }
252 } // namespace ranges
253 
254 #include <range/v3/detail/epilogue.hpp>
255 
256 #endif
std::integral_constant< std::size_t, N > size_t
An integral constant wrapper for std::size_t.
Definition: meta.hpp:163
front< Pair > first
Retrieve the first element of the pair Pair.
Definition: meta.hpp:2251
_t< detail::count_< L, T > > count
Count the number of times a type T appears in the list L.
Definition: meta.hpp:2725
Tiny meta-programming library.
An empty type.
Definition: meta.hpp:135
Definition: associated_types.hpp:236
Definition: memory.hpp:165
Definition: memory.hpp:223
Definition: memory.hpp:104