You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

252 lines
7.1KB

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