memory.hpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /// \file
  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. #include <cstdint>
  24. #include <memory>
  25. #include <type_traits>
  26. #include <utility>
  27. #include <meta/meta.hpp>
  28. #include <range/v3/detail/config.hpp>
  29. #include <range/v3/iterator/concepts.hpp>
  30. #include <range/v3/iterator/traits.hpp>
  31. #include <range/v3/utility/polymorphic_cast.hpp>
  32. #include <range/v3/detail/prologue.hpp>
  33. namespace ranges
  34. {
  35. /// \cond
  36. namespace detail
  37. {
  38. template<typename T>
  39. std::pair<T *, std::ptrdiff_t> get_temporary_buffer_impl(std::size_t n) noexcept
  40. {
  41. if(n > PTRDIFF_MAX / sizeof(T))
  42. n = PTRDIFF_MAX / sizeof(T);
  43. void * ptr = nullptr;
  44. for(; ptr == nullptr && n > 0; n /= 2)
  45. {
  46. #if RANGES_CXX_ALIGNED_NEW < RANGES_CXX_ALIGNED_NEW_17
  47. static_assert(alignof(T) <= alignof(std::max_align_t),
  48. "Sorry: over-aligned types are supported only with C++17.");
  49. #else // RANGES_CXX_ALIGNED_NEW
  50. if(RANGES_CONSTEXPR_IF(alignof(T) > __STDCPP_DEFAULT_NEW_ALIGNMENT__))
  51. ptr = ::operator new(
  52. sizeof(T) * n, std::align_val_t{alignof(T)}, std::nothrow);
  53. else
  54. #endif // RANGES_CXX_ALIGNED_NEW
  55. ptr = ::operator new(sizeof(T) * n, std::nothrow);
  56. }
  57. return {static_cast<T *>(ptr), static_cast<std::ptrdiff_t>(n)};
  58. }
  59. template<typename T, typename D>
  60. std::pair<T *, std::ptrdiff_t> get_temporary_buffer(D count) noexcept
  61. {
  62. RANGES_EXPECT(count >= 0);
  63. return detail::get_temporary_buffer_impl<T>(static_cast<std::size_t>(count));
  64. }
  65. struct return_temporary_buffer
  66. {
  67. template<typename T>
  68. void operator()(T * p) const
  69. {
  70. #if RANGES_CXX_ALIGNED_NEW < RANGES_CXX_ALIGNED_NEW_17
  71. static_assert(alignof(T) <= alignof(std::max_align_t),
  72. "Sorry: over-aligned types are supported only with C++17.");
  73. #else // RANGES_CXX_ALIGNED_NEW
  74. if(RANGES_CONSTEXPR_IF(alignof(T) > __STDCPP_DEFAULT_NEW_ALIGNMENT__))
  75. ::operator delete(p, std::align_val_t{alignof(T)});
  76. else
  77. #endif // RANGES_CXX_ALIGNED_NEW
  78. ::operator delete(p);
  79. }
  80. };
  81. template(typename T, typename... Args)(
  82. requires (!std::is_array<T>::value)) //
  83. std::unique_ptr<T> make_unique(Args &&... args)
  84. {
  85. return std::unique_ptr<T>{new T(static_cast<Args &&>(args)...)};
  86. }
  87. } // namespace detail
  88. /// \endcond
  89. /// \addtogroup group-utility
  90. /// @{
  91. template<typename O, typename Val>
  92. struct raw_storage_iterator
  93. {
  94. private:
  95. CPP_assert(output_iterator<O, Val>);
  96. CPP_assert(std::is_lvalue_reference<iter_reference_t<O>>());
  97. O out_;
  98. public:
  99. using difference_type = iter_difference_t<O>;
  100. raw_storage_iterator() = default;
  101. explicit raw_storage_iterator(O out)
  102. : out_(std::move(out))
  103. {}
  104. raw_storage_iterator & operator*() noexcept
  105. {
  106. return *this;
  107. }
  108. CPP_member
  109. auto operator=(Val const & val) //
  110. -> CPP_ret(raw_storage_iterator &)(
  111. requires copy_constructible<Val>)
  112. {
  113. ::new((void *)std::addressof(*out_)) Val(val);
  114. return *this;
  115. }
  116. CPP_member
  117. auto operator=(Val && val) //
  118. -> CPP_ret(raw_storage_iterator &)(
  119. requires move_constructible<Val>)
  120. {
  121. ::new((void *)std::addressof(*out_)) Val(std::move(val));
  122. return *this;
  123. }
  124. raw_storage_iterator & operator++()
  125. {
  126. ++out_;
  127. return *this;
  128. }
  129. CPP_member
  130. auto operator++(int) //
  131. -> CPP_ret(void)(
  132. requires (!forward_iterator<O>))
  133. {
  134. ++out_;
  135. }
  136. CPP_member
  137. auto operator++(int) //
  138. -> CPP_ret(raw_storage_iterator)(
  139. requires forward_iterator<O>)
  140. {
  141. auto tmp = *this;
  142. ++out_;
  143. return tmp;
  144. }
  145. O base() const
  146. {
  147. return out_;
  148. }
  149. };
  150. template<typename I>
  151. struct iterator_wrapper
  152. {
  153. private:
  154. CPP_assert(input_or_output_iterator<I>);
  155. mutable I * i_ = nullptr;
  156. public:
  157. using difference_type = iter_difference_t<I>;
  158. iterator_wrapper() = default;
  159. iterator_wrapper(iterator_wrapper const & that)
  160. : i_(that.i_)
  161. {
  162. that.i_ = nullptr;
  163. }
  164. iterator_wrapper & operator=(iterator_wrapper const & that)
  165. {
  166. i_ = that.i_;
  167. that.i_ = nullptr;
  168. return *this;
  169. }
  170. iterator_wrapper(I & i)
  171. : i_(std::addressof(i))
  172. {}
  173. // clang-format off
  174. auto CPP_auto_fun(operator*)()(const)
  175. (
  176. return **i_
  177. )
  178. // clang-format on
  179. iterator_wrapper &
  180. operator++()
  181. {
  182. ++*i_;
  183. return *this;
  184. }
  185. void operator++(int)
  186. {
  187. ++*i_;
  188. }
  189. I base() const
  190. {
  191. return *i_;
  192. }
  193. };
  194. template(typename I)(
  195. requires input_or_output_iterator<I>)
  196. iterator_wrapper<I> iter_ref(I & i)
  197. {
  198. return i;
  199. }
  200. template<typename I>
  201. struct indirectly_readable_traits<iterator_wrapper<I>>
  202. : meta::if_c<(bool)input_iterator<I>, indirectly_readable_traits<I>, meta::nil_>
  203. {};
  204. template<typename Val>
  205. struct raw_buffer
  206. {
  207. private:
  208. Val * begin_;
  209. raw_storage_iterator<Val *, Val> rsi_;
  210. public:
  211. explicit raw_buffer(Val * first)
  212. : begin_(first)
  213. , rsi_(first)
  214. {}
  215. raw_buffer(raw_buffer &&) = default;
  216. raw_buffer(raw_buffer const &) = delete;
  217. ~raw_buffer()
  218. {
  219. for(; begin_ != rsi_.base(); ++begin_)
  220. begin_->~Val();
  221. }
  222. iterator_wrapper<raw_storage_iterator<Val *, Val>> begin()
  223. {
  224. return ranges::iter_ref(rsi_);
  225. }
  226. };
  227. template<typename Val>
  228. raw_buffer<Val> make_raw_buffer(Val * val)
  229. {
  230. return raw_buffer<Val>(val);
  231. }
  232. /// @}
  233. } // namespace ranges
  234. #include <range/v3/detail/epilogue.hpp>
  235. #endif