Horizon
Loading...
Searching...
No Matches
memory.hpp
Go to the documentation of this file.
1
2// 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
38namespace 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;
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)(
211 iterator_wrapper<I> iter_ref(I & i)
212 {
213 return i;
214 }
215
216 template<typename I>
220
221 template<typename Val>
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;
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
The forward_iterator concept.
The input_iterator concept.
The input_or_output_iterator concept.
The output_iterator concept.
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