sequence_container_interface.hpp 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043
  1. // Copyright (C) 2019 T. Zachary Laine
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See
  4. // accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_STL_INTERFACES_CONTAINER_INTERFACE_HPP
  7. #define BOOST_STL_INTERFACES_CONTAINER_INTERFACE_HPP
  8. #include <boost/stl_interfaces/reverse_iterator.hpp>
  9. #include <boost/assert.hpp>
  10. #include <boost/config.hpp>
  11. #include <algorithm>
  12. #include <stdexcept>
  13. #include <cstddef>
  14. namespace boost { namespace stl_interfaces { namespace detail {
  15. template<typename T, typename SizeType>
  16. struct n_iter : iterator_interface<
  17. #if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS
  18. n_iter<T, SizeType>,
  19. #endif
  20. std::random_access_iterator_tag,
  21. T>
  22. {
  23. n_iter() : x_(nullptr), n_(0) {}
  24. n_iter(T const & x, SizeType n) : x_(&x), n_(n) {}
  25. T const & operator*() const { return *x_; }
  26. constexpr std::ptrdiff_t operator-(n_iter other) const noexcept
  27. {
  28. return std::ptrdiff_t(n_) - std::ptrdiff_t(other.n_);
  29. }
  30. n_iter & operator+=(std::ptrdiff_t offset)
  31. {
  32. n_ += offset;
  33. return *this;
  34. }
  35. private:
  36. T const * x_;
  37. SizeType n_;
  38. };
  39. template<typename T, typename SizeType>
  40. constexpr auto make_n_iter(T const & x, SizeType n) noexcept(
  41. noexcept(n_iter<T, SizeType>(x, n)))
  42. {
  43. using result_type = n_iter<T, SizeType>;
  44. return result_type(x, SizeType(0));
  45. }
  46. template<typename T, typename SizeType>
  47. constexpr auto make_n_iter_end(T const & x, SizeType n) noexcept(
  48. noexcept(n_iter<T, SizeType>(x, n)))
  49. {
  50. return n_iter<T, SizeType>(x, n);
  51. }
  52. template<typename Container>
  53. std::size_t fake_capacity(Container const & c)
  54. {
  55. return SIZE_MAX;
  56. }
  57. template<
  58. typename Container,
  59. typename Enable = decltype(
  60. std::size_t() = std::declval<Container const &>().capacity())>
  61. std::size_t fake_capacity(Container const & c)
  62. {
  63. return c.capacity();
  64. }
  65. }}}
  66. namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V1 {
  67. /** A CRTP template that one may derive from to make it easier to define
  68. container types.
  69. The template parameter `D` for `sequence_container_interface` may be
  70. an incomplete type. Before any member of the resulting specialization
  71. of `sequence_container_interface` other than special member functions
  72. is referenced, `D` shall be complete; shall model
  73. `std::derived_from<sequence_container_interface<D>>`,
  74. `std::semiregular`, and `std::forward_range`; and shall contain all
  75. the nested types required in Table 72: Container requirements and, for
  76. those whose iterator nested type models `std::bidirectinal_iterator`,
  77. those in Table 73: Reversible container requirements.
  78. For an object `d` of type `D`, a call to `std::ranges::begin(d)` sxhall
  79. not mutate any data members of `d`, and `d`'s destructor shall end the
  80. lifetimes of the objects in `[std::ranges::begin(d),
  81. std::ranges::end(d))`. */
  82. template<
  83. typename Derived,
  84. element_layout Contiguity = element_layout::discontiguous
  85. #ifndef BOOST_STL_INTERFACES_DOXYGEN
  86. ,
  87. typename E = std::enable_if_t<
  88. std::is_class<Derived>::value &&
  89. std::is_same<Derived, std::remove_cv_t<Derived>>::value>
  90. #endif
  91. >
  92. struct sequence_container_interface;
  93. namespace v1_dtl {
  94. template<typename Iter>
  95. using in_iter = std::is_convertible<
  96. typename std::iterator_traits<Iter>::iterator_category,
  97. std::input_iterator_tag>;
  98. template<typename D, typename = void>
  99. struct clear_impl
  100. {
  101. static constexpr void call(D & d) noexcept {}
  102. };
  103. template<typename D>
  104. struct clear_impl<D, void_t<decltype(std::declval<D>().clear())>>
  105. {
  106. static constexpr void call(D & d) noexcept { d.clear(); }
  107. };
  108. template<typename D, element_layout Contiguity>
  109. void derived_container(sequence_container_interface<D, Contiguity> const &);
  110. }
  111. template<
  112. typename Derived,
  113. element_layout Contiguity
  114. #ifndef BOOST_STL_INTERFACES_DOXYGEN
  115. ,
  116. typename E
  117. #endif
  118. >
  119. struct sequence_container_interface
  120. {
  121. #ifndef BOOST_STL_INTERFACES_DOXYGEN
  122. private:
  123. constexpr Derived & derived() noexcept
  124. {
  125. return static_cast<Derived &>(*this);
  126. }
  127. constexpr const Derived & derived() const noexcept
  128. {
  129. return static_cast<Derived const &>(*this);
  130. }
  131. constexpr Derived & mutable_derived() const noexcept
  132. {
  133. return const_cast<Derived &>(static_cast<Derived const &>(*this));
  134. }
  135. #endif
  136. public:
  137. template<typename D = Derived>
  138. constexpr auto empty() noexcept(
  139. noexcept(std::declval<D &>().begin() == std::declval<D &>().end()))
  140. -> decltype(
  141. std::declval<D &>().begin() == std::declval<D &>().end())
  142. {
  143. return derived().begin() == derived().end();
  144. }
  145. template<typename D = Derived>
  146. constexpr auto empty() const noexcept(noexcept(
  147. std::declval<D const &>().begin() ==
  148. std::declval<D const &>().end()))
  149. -> decltype(
  150. std::declval<D const &>().begin() ==
  151. std::declval<D const &>().end())
  152. {
  153. return derived().begin() == derived().end();
  154. }
  155. template<
  156. typename D = Derived,
  157. element_layout C = Contiguity,
  158. typename Enable = std::enable_if_t<C == element_layout::contiguous>>
  159. constexpr auto data() noexcept(noexcept(std::declval<D &>().begin()))
  160. -> decltype(std::addressof(*std::declval<D &>().begin()))
  161. {
  162. return std::addressof(*derived().begin());
  163. }
  164. template<
  165. typename D = Derived,
  166. element_layout C = Contiguity,
  167. typename Enable = std::enable_if_t<C == element_layout::contiguous>>
  168. constexpr auto data() const
  169. noexcept(noexcept(std::declval<D const &>().begin()))
  170. -> decltype(std::addressof(*std::declval<D const &>().begin()))
  171. {
  172. return std::addressof(*derived().begin());
  173. }
  174. template<typename D = Derived>
  175. constexpr auto size()
  176. #if !BOOST_CLANG
  177. noexcept(noexcept(
  178. std::declval<D &>().end() - std::declval<D &>().begin()))
  179. #endif
  180. -> decltype(typename D::size_type(
  181. std::declval<D &>().end() - std::declval<D &>().begin()))
  182. {
  183. return derived().end() - derived().begin();
  184. }
  185. template<typename D = Derived>
  186. constexpr auto size() const noexcept(noexcept(
  187. std::declval<D const &>().end() -
  188. std::declval<D const &>().begin()))
  189. -> decltype(typename D::size_type(
  190. #if !BOOST_CLANG
  191. std::declval<D const &>().end() -
  192. std::declval<D const &>().begin()
  193. #endif
  194. ))
  195. {
  196. return derived().end() - derived().begin();
  197. }
  198. template<typename D = Derived>
  199. constexpr auto front() noexcept(noexcept(*std::declval<D &>().begin()))
  200. -> decltype(*std::declval<D &>().begin())
  201. {
  202. return *derived().begin();
  203. }
  204. template<typename D = Derived>
  205. constexpr auto front() const
  206. noexcept(noexcept(*std::declval<D const &>().begin()))
  207. -> decltype(*std::declval<D const &>().begin())
  208. {
  209. return *derived().begin();
  210. }
  211. template<typename D = Derived>
  212. constexpr auto push_front(typename D::value_type const & x) noexcept(
  213. noexcept(std::declval<D &>().emplace_front(x)))
  214. -> decltype((void)std::declval<D &>().emplace_front(x))
  215. {
  216. derived().emplace_front(x);
  217. }
  218. template<typename D = Derived>
  219. constexpr auto push_front(typename D::value_type && x) noexcept(
  220. noexcept(std::declval<D &>().emplace_front(std::move(x))))
  221. -> decltype((void)std::declval<D &>().emplace_front(std::move(x)))
  222. {
  223. derived().emplace_front(std::move(x));
  224. }
  225. template<typename D = Derived>
  226. constexpr auto pop_front() noexcept -> decltype(
  227. std::declval<D &>().emplace_front(
  228. std::declval<typename D::value_type &>()),
  229. (void)std::declval<D &>().erase(std::declval<D &>().begin()))
  230. {
  231. derived().erase(derived().begin());
  232. }
  233. template<
  234. typename D = Derived,
  235. typename Enable = std::enable_if_t<
  236. v1_dtl::decrementable_sentinel<D>::value &&
  237. v1_dtl::common_range<D>::value>>
  238. constexpr auto
  239. back() noexcept(noexcept(*std::prev(std::declval<D &>().end())))
  240. -> decltype(*std::prev(std::declval<D &>().end()))
  241. {
  242. return *std::prev(derived().end());
  243. }
  244. template<
  245. typename D = Derived,
  246. typename Enable = std::enable_if_t<
  247. v1_dtl::decrementable_sentinel<D>::value &&
  248. v1_dtl::common_range<D>::value>>
  249. constexpr auto back() const
  250. noexcept(noexcept(*std::prev(std::declval<D const &>().end())))
  251. -> decltype(*std::prev(std::declval<D const &>().end()))
  252. {
  253. return *std::prev(derived().end());
  254. }
  255. template<typename D = Derived>
  256. constexpr auto push_back(typename D::value_type const & x) noexcept(
  257. noexcept(std::declval<D &>().emplace_back(x)))
  258. -> decltype((void)std::declval<D &>().emplace_back(x))
  259. {
  260. derived().emplace_back(x);
  261. }
  262. template<typename D = Derived>
  263. constexpr auto push_back(typename D::value_type && x) noexcept(
  264. noexcept(std::declval<D &>().emplace_back(std::move(x))))
  265. -> decltype((void)std::declval<D &>().emplace_back(std::move(x)))
  266. {
  267. derived().emplace_back(std::move(x));
  268. }
  269. template<typename D = Derived>
  270. constexpr auto pop_back() noexcept -> decltype(
  271. std::declval<D &>().emplace_back(
  272. std::declval<typename D::value_type>()),
  273. (void)std::declval<D &>().erase(
  274. std::prev(std::declval<D &>().end())))
  275. {
  276. derived().erase(std::prev(derived().end()));
  277. }
  278. template<typename D = Derived>
  279. constexpr auto operator[](typename D::size_type n) noexcept(
  280. noexcept(std::declval<D &>().begin()[n]))
  281. -> decltype(std::declval<D &>().begin()[n])
  282. {
  283. return derived().begin()[n];
  284. }
  285. template<typename D = Derived>
  286. constexpr auto operator[](typename D::size_type n) const
  287. noexcept(noexcept(std::declval<D const &>().begin()[n]))
  288. -> decltype(std::declval<D const &>().begin()[n])
  289. {
  290. return derived().begin()[n];
  291. }
  292. template<typename D = Derived>
  293. constexpr auto at(typename D::size_type i)
  294. -> decltype(std::declval<D &>().size(), std::declval<D &>()[i])
  295. {
  296. if (derived().size() <= i) {
  297. throw std::out_of_range(
  298. "Bounds check failed in sequence_container_interface::at()");
  299. }
  300. return derived()[i];
  301. }
  302. template<typename D = Derived>
  303. constexpr auto at(typename D::size_type i) const -> decltype(
  304. std::declval<D const &>().size(), std::declval<D const &>()[i])
  305. {
  306. if (derived().size() <= i) {
  307. throw std::out_of_range(
  308. "Bounds check failed in sequence_container_interface::at()");
  309. }
  310. return derived()[i];
  311. }
  312. template<typename D = Derived, typename Iter = typename D::const_iterator>
  313. constexpr Iter begin() const
  314. noexcept(noexcept(std::declval<D &>().begin()))
  315. {
  316. return Iter(mutable_derived().begin());
  317. }
  318. template<typename D = Derived, typename Iter = typename D::const_iterator>
  319. constexpr Iter end() const noexcept(noexcept(std::declval<D &>().end()))
  320. {
  321. return Iter(mutable_derived().end());
  322. }
  323. template<typename D = Derived>
  324. constexpr auto cbegin() const
  325. noexcept(noexcept(std::declval<D const &>().begin()))
  326. -> decltype(std::declval<D const &>().begin())
  327. {
  328. return derived().begin();
  329. }
  330. template<typename D = Derived>
  331. constexpr auto cend() const
  332. noexcept(noexcept(std::declval<D const &>().end()))
  333. -> decltype(std::declval<D const &>().end())
  334. {
  335. return derived().end();
  336. }
  337. template<
  338. typename D = Derived,
  339. typename Enable = std::enable_if_t<v1_dtl::common_range<D>::value>>
  340. constexpr auto rbegin() noexcept(noexcept(
  341. stl_interfaces::make_reverse_iterator(std::declval<D &>().end())))
  342. {
  343. return stl_interfaces::make_reverse_iterator(derived().end());
  344. }
  345. template<
  346. typename D = Derived,
  347. typename Enable = std::enable_if_t<v1_dtl::common_range<D>::value>>
  348. constexpr auto rend() noexcept(noexcept(
  349. stl_interfaces::make_reverse_iterator(std::declval<D &>().begin())))
  350. {
  351. return stl_interfaces::make_reverse_iterator(derived().begin());
  352. }
  353. template<typename D = Derived>
  354. constexpr auto rbegin() const
  355. noexcept(noexcept(std::declval<D &>().rbegin()))
  356. {
  357. return
  358. typename D::const_reverse_iterator(mutable_derived().rbegin());
  359. }
  360. template<typename D = Derived>
  361. constexpr auto rend() const
  362. noexcept(noexcept(std::declval<D &>().rend()))
  363. {
  364. return typename D::const_reverse_iterator(mutable_derived().rend());
  365. }
  366. template<typename D = Derived>
  367. constexpr auto crbegin() const
  368. noexcept(noexcept(std::declval<D const &>().rbegin()))
  369. -> decltype(std::declval<D const &>().rbegin())
  370. {
  371. return derived().rbegin();
  372. }
  373. template<typename D = Derived>
  374. constexpr auto crend() const
  375. noexcept(noexcept(std::declval<D const &>().rend()))
  376. -> decltype(std::declval<D const &>().rend())
  377. {
  378. return derived().rend();
  379. }
  380. template<typename D = Derived>
  381. constexpr auto insert(
  382. typename D::const_iterator pos,
  383. typename D::value_type const &
  384. x) noexcept(noexcept(std::declval<D &>().emplace(pos, x)))
  385. -> decltype(std::declval<D &>().emplace(pos, x))
  386. {
  387. return derived().emplace(pos, x);
  388. }
  389. template<typename D = Derived>
  390. constexpr auto insert(
  391. typename D::const_iterator pos,
  392. typename D::value_type &&
  393. x) noexcept(noexcept(std::declval<D &>()
  394. .emplace(pos, std::move(x))))
  395. -> decltype(std::declval<D &>().emplace(pos, std::move(x)))
  396. {
  397. return derived().emplace(pos, std::move(x));
  398. }
  399. template<typename D = Derived>
  400. constexpr auto insert(
  401. typename D::const_iterator pos,
  402. typename D::size_type n,
  403. typename D::value_type const & x)
  404. // If you see an error in this noexcept() expression, that's
  405. // because this function is not properly constrained. In other
  406. // words, Derived does not have a "range" insert like
  407. // insert(position, first, last). If that is the case, this
  408. // function should be removed via SFINAE from overload resolution.
  409. // However, both the trailing decltype code below and a
  410. // std::enable_if in the template parameters do not work. Sorry
  411. // about that. See below for details.
  412. noexcept(noexcept(std::declval<D &>().insert(
  413. pos, detail::make_n_iter(x, n), detail::make_n_iter_end(x, n))))
  414. // This causes the compiler to infinitely recurse into this function's
  415. // declaration, even though the call below does not match the
  416. // signature of this function.
  417. #if 0
  418. -> decltype(std::declval<D &>().insert(
  419. pos, detail::make_n_iter(x, n), detail::make_n_iter_end(x, n)))
  420. #endif
  421. {
  422. return derived().insert(
  423. pos, detail::make_n_iter(x, n), detail::make_n_iter_end(x, n));
  424. }
  425. template<typename D = Derived>
  426. constexpr auto insert(
  427. typename D::const_iterator pos,
  428. std::initializer_list<typename D::value_type>
  429. il) noexcept(noexcept(std::declval<D &>()
  430. .insert(pos, il.begin(), il.end())))
  431. -> decltype(std::declval<D &>().insert(pos, il.begin(), il.end()))
  432. {
  433. return derived().insert(pos, il.begin(), il.end());
  434. }
  435. template<typename D = Derived>
  436. constexpr auto erase(typename D::const_iterator pos) noexcept
  437. -> decltype(std::declval<D &>().erase(pos, std::next(pos)))
  438. {
  439. return derived().erase(pos, std::next(pos));
  440. }
  441. template<
  442. typename InputIterator,
  443. typename D = Derived,
  444. typename Enable =
  445. std::enable_if_t<v1_dtl::in_iter<InputIterator>::value>>
  446. constexpr auto assign(InputIterator first, InputIterator last) noexcept(
  447. noexcept(std::declval<D &>().insert(
  448. std::declval<D &>().begin(), first, last)))
  449. -> decltype(
  450. std::declval<D &>().erase(
  451. std::declval<D &>().begin(), std::declval<D &>().end()),
  452. (void)std::declval<D &>().insert(
  453. std::declval<D &>().begin(), first, last))
  454. {
  455. auto out = derived().begin();
  456. auto const out_last = derived().end();
  457. for (; out != out_last && first != last; ++first, ++out) {
  458. *out = *first;
  459. }
  460. if (out != out_last)
  461. derived().erase(out, out_last);
  462. if (first != last)
  463. derived().insert(derived().end(), first, last);
  464. }
  465. template<typename D = Derived>
  466. constexpr auto assign(
  467. typename D::size_type n,
  468. typename D::value_type const &
  469. x) noexcept(noexcept(std::declval<D &>()
  470. .insert(
  471. std::declval<D &>().begin(),
  472. detail::make_n_iter(x, n),
  473. detail::make_n_iter_end(x, n))))
  474. -> decltype(
  475. std::declval<D &>().size(),
  476. std::declval<D &>().erase(
  477. std::declval<D &>().begin(), std::declval<D &>().end()),
  478. (void)std::declval<D &>().insert(
  479. std::declval<D &>().begin(),
  480. detail::make_n_iter(x, n),
  481. detail::make_n_iter_end(x, n)))
  482. {
  483. if (detail::fake_capacity(derived()) < n) {
  484. Derived temp(n, x);
  485. derived().swap(temp);
  486. } else {
  487. auto const min_size =
  488. std::min<std::ptrdiff_t>(n, derived().size());
  489. auto const fill_end =
  490. std::fill_n(derived().begin(), min_size, x);
  491. if (min_size < (std::ptrdiff_t)derived().size()) {
  492. derived().erase(fill_end, derived().end());
  493. } else {
  494. n -= min_size;
  495. derived().insert(
  496. derived().begin(),
  497. detail::make_n_iter(x, n),
  498. detail::make_n_iter_end(x, n));
  499. }
  500. }
  501. }
  502. template<typename D = Derived>
  503. constexpr auto
  504. assign(std::initializer_list<typename D::value_type> il) noexcept(
  505. noexcept(std::declval<D &>().assign(il.begin(), il.end())))
  506. -> decltype((void)std::declval<D &>().assign(il.begin(), il.end()))
  507. {
  508. derived().assign(il.begin(), il.end());
  509. }
  510. template<typename D = Derived>
  511. constexpr auto
  512. operator=(std::initializer_list<typename D::value_type> il) noexcept(
  513. noexcept(std::declval<D &>().assign(il.begin(), il.end())))
  514. -> decltype(
  515. std::declval<D &>().assign(il.begin(), il.end()),
  516. std::declval<D &>())
  517. {
  518. derived().assign(il.begin(), il.end());
  519. return *this;
  520. }
  521. template<typename D = Derived>
  522. constexpr auto clear() noexcept
  523. -> decltype((void)std::declval<D &>().erase(
  524. std::declval<D &>().begin(), std::declval<D &>().end()))
  525. {
  526. derived().erase(derived().begin(), derived().end());
  527. }
  528. };
  529. /** Implementation of free function `swap()` for all containers derived
  530. from `sequence_container_interface`. */
  531. template<typename ContainerInterface>
  532. constexpr auto swap(
  533. ContainerInterface & lhs,
  534. ContainerInterface & rhs) noexcept(noexcept(lhs.swap(rhs)))
  535. -> decltype(v1_dtl::derived_container(lhs), lhs.swap(rhs))
  536. {
  537. return lhs.swap(rhs);
  538. }
  539. /** Implementation of `operator==()` for all containers derived from
  540. `sequence_container_interface`. */
  541. template<typename ContainerInterface>
  542. constexpr auto
  543. operator==(ContainerInterface const & lhs, ContainerInterface const & rhs) noexcept(
  544. noexcept(lhs.size() == rhs.size()) &&
  545. noexcept(*lhs.begin() == *rhs.begin()))
  546. -> decltype(
  547. v1_dtl::derived_container(lhs),
  548. lhs.size() == rhs.size(),
  549. *lhs.begin() == *rhs.begin(),
  550. true)
  551. {
  552. return lhs.size() == rhs.size() &&
  553. std::equal(lhs.begin(), lhs.end(), rhs.begin());
  554. }
  555. /** Implementation of `operator!=()` for all containers derived from
  556. `sequence_container_interface`. */
  557. template<typename ContainerInterface>
  558. constexpr auto operator!=(
  559. ContainerInterface const & lhs,
  560. ContainerInterface const & rhs) noexcept(noexcept(lhs == rhs))
  561. -> decltype(v1_dtl::derived_container(lhs), lhs == rhs)
  562. {
  563. return !(lhs == rhs);
  564. }
  565. /** Implementation of `operator<()` for all containers derived from
  566. `sequence_container_interface`. */
  567. template<typename ContainerInterface>
  568. constexpr auto operator<(
  569. ContainerInterface const & lhs,
  570. ContainerInterface const &
  571. rhs) noexcept(noexcept(*lhs.begin() < *rhs.begin()))
  572. -> decltype(
  573. v1_dtl::derived_container(lhs), *lhs.begin() < *rhs.begin(), true)
  574. {
  575. auto it1 = lhs.begin();
  576. auto const last1 = lhs.end();
  577. auto it2 = rhs.begin();
  578. auto const last2 = rhs.end();
  579. for (; it1 != last1 && it2 != last2; ++it1, ++it2) {
  580. if (*it1 < *it2)
  581. return true;
  582. if (*it2 < *it1)
  583. return false;
  584. }
  585. return it1 == last1 && it2 != last2;
  586. }
  587. /** Implementation of `operator<=()` for all containers derived from
  588. `sequence_container_interface`. */
  589. template<typename ContainerInterface>
  590. constexpr auto operator<=(
  591. ContainerInterface const & lhs,
  592. ContainerInterface const & rhs) noexcept(noexcept(lhs < rhs))
  593. -> decltype(v1_dtl::derived_container(lhs), lhs < rhs)
  594. {
  595. return !(rhs < lhs);
  596. }
  597. /** Implementation of `operator>()` for all containers derived from
  598. `sequence_container_interface`. */
  599. template<typename ContainerInterface>
  600. constexpr auto operator>(
  601. ContainerInterface const & lhs,
  602. ContainerInterface const & rhs) noexcept(noexcept(lhs < rhs))
  603. -> decltype(v1_dtl::derived_container(lhs), lhs < rhs)
  604. {
  605. return rhs < lhs;
  606. }
  607. /** Implementation of `operator>=()` for all containers derived from
  608. `sequence_container_interface`. */
  609. template<typename ContainerInterface>
  610. constexpr auto operator>=(
  611. ContainerInterface const & lhs,
  612. ContainerInterface const & rhs) noexcept(noexcept(lhs < rhs))
  613. -> decltype(v1_dtl::derived_container(lhs), lhs < rhs)
  614. {
  615. return !(lhs < rhs);
  616. }
  617. }}}
  618. #if defined(BOOST_STL_INTERFACES_DOXYGEN) || BOOST_STL_INTERFACES_USE_CONCEPTS
  619. namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V2 {
  620. namespace v2_dtl {
  621. // This needs to become an exposition-only snake-case template alias
  622. // when standardized.
  623. template<typename T>
  624. using container_size_t = typename T::size_type;
  625. template<typename T, typename I>
  626. // clang-format off
  627. concept range_insert =
  628. requires (T t, std::ranges::iterator_t<T> t_it, I it) {
  629. t.template insert<I>(t_it, it, it);
  630. // clang-format on
  631. };
  632. template<typename T>
  633. using n_iter_t =
  634. detail::n_iter<std::ranges::range_value_t<T>, container_size_t<T>>;
  635. }
  636. // clang-format off
  637. /** A CRTP template that one may derive from to make it easier to define
  638. container types.
  639. The template parameter `D` for `sequence_container_interface` may be
  640. an incomplete type. Before any member of the resulting specialization
  641. of `sequence_container_interface` other than special member functions
  642. is referenced, `D` shall be complete; shall model
  643. `std::derived_from<sequence_container_interface<D>>`,
  644. `std::semiregular`, and `std::forward_range`; and shall contain all
  645. the nested types required in Table 72: Container requirements and, for
  646. those whose iterator nested type models `std::bidirectinal_iterator`,
  647. those in Table 73: Reversible container requirements.
  648. For an object `d` of type `D`, a call to `std::ranges::begin(d)` shall
  649. not mutate any data members of `d`, and `d`'s destructor shall end the
  650. lifetimes of the objects in `[std::ranges::begin(d),
  651. std::ranges::end(d))`.
  652. The `Contiguity` template parameter is not needed, and is unused. It
  653. only exists to make the transition from `namespace v1` to `namespace
  654. v2` seamless. */
  655. template<typename D,
  656. element_layout Contiguity = element_layout::discontiguous>
  657. requires std::is_class_v<D> && std::same_as<D, std::remove_cv_t<D>>
  658. struct sequence_container_interface
  659. {
  660. private:
  661. constexpr D& derived() noexcept {
  662. return static_cast<D&>(*this);
  663. }
  664. constexpr const D& derived() const noexcept {
  665. return static_cast<const D&>(*this);
  666. }
  667. constexpr D & mutable_derived() const noexcept {
  668. return const_cast<D&>(static_cast<const D&>(*this));
  669. }
  670. static constexpr void clear_impl(D& d) noexcept {}
  671. static constexpr void clear_impl(D& d) noexcept
  672. requires requires { d.clear(); }
  673. { d.clear(); }
  674. public:
  675. constexpr bool empty() const {
  676. return std::ranges::begin(derived()) == std::ranges::end(derived());
  677. }
  678. constexpr auto data() requires std::contiguous_iterator<std::ranges::iterator_t<D>> {
  679. return std::to_address(std::ranges::begin(derived()));
  680. }
  681. constexpr auto data() const requires std::contiguous_iterator<std::ranges::iterator_t<const D>> {
  682. return std::to_address(std::ranges::begin(derived()));
  683. }
  684. template<typename C = D>
  685. constexpr v2_dtl::container_size_t<C> size() const
  686. requires std::sized_sentinel_for<std::ranges::sentinel_t<const C>, std::ranges::iterator_t<const C>> {
  687. return v2_dtl::container_size_t<C>(
  688. std::ranges::end(derived()) - std::ranges::begin(derived()));
  689. }
  690. constexpr decltype(auto) front() {
  691. BOOST_ASSERT(!empty());
  692. return *std::ranges::begin(derived());
  693. }
  694. constexpr decltype(auto) front() const {
  695. BOOST_ASSERT(!empty());
  696. return *std::ranges::begin(derived());
  697. }
  698. template<typename C = D>
  699. constexpr void push_front(const std::ranges::range_value_t<C>& x)
  700. requires requires (D d) { d.emplace_front(x); } {
  701. derived().emplace_front(x);
  702. }
  703. template<typename C = D>
  704. constexpr void push_front(std::ranges::range_value_t<C>&& x)
  705. requires requires (D d) { d.emplace_front(std::move(x)); } {
  706. derived().emplace_front(std::move(x));
  707. }
  708. constexpr void pop_front() noexcept
  709. requires requires (D d, const std::ranges::range_value_t<D>& x, std::ranges::iterator_t<D> position) {
  710. d.emplace_front(x);
  711. d.erase(position);
  712. } {
  713. return derived().erase(std::ranges::begin(derived()));
  714. }
  715. constexpr decltype(auto) back()
  716. requires std::ranges::bidirectional_range<D> && std::ranges::common_range<D> {
  717. BOOST_ASSERT(!empty());
  718. return *std::ranges::prev(std::ranges::end(derived()));
  719. }
  720. constexpr decltype(auto) back() const
  721. requires std::ranges::bidirectional_range<const D> && std::ranges::common_range<const D> {
  722. BOOST_ASSERT(!empty());
  723. return *std::ranges::prev(std::ranges::end(derived()));
  724. }
  725. template<std::ranges::bidirectional_range C = D>
  726. constexpr void push_back(const std::ranges::range_value_t<C>& x)
  727. requires std::ranges::common_range<C> && requires (D d) { d.emplace_back(x); } {
  728. derived().emplace_back(x);
  729. }
  730. template<std::ranges::bidirectional_range C = D>
  731. constexpr void push_back(std::ranges::range_value_t<C>&& x)
  732. requires std::ranges::common_range<C> && requires (D d) { d.emplace_back(std::move(x)); } {
  733. derived().emplace_back(std::move(x));
  734. }
  735. constexpr void pop_back() noexcept
  736. requires std::ranges::bidirectional_range<D> && std::ranges::common_range<D> &&
  737. requires (D d, std::ranges::range_value_t<D> x, std::ranges::iterator_t<D> position) {
  738. d.emplace_back(std::move(x));
  739. d.erase(position);
  740. } {
  741. return derived().erase(std::ranges::prev(std::ranges::end(derived())));
  742. }
  743. template<std::ranges::random_access_range C = D>
  744. constexpr decltype(auto) operator[](v2_dtl::container_size_t<C> n) {
  745. return std::ranges::begin(derived())[n];
  746. }
  747. template<std::ranges::random_access_range C = const D>
  748. constexpr decltype(auto) operator[](v2_dtl::container_size_t<C> n) const {
  749. return std::ranges::begin(derived())[n];
  750. }
  751. template<std::ranges::random_access_range C = D>
  752. constexpr decltype(auto) at(v2_dtl::container_size_t<C> n) {
  753. if (derived().size() <= n)
  754. throw std::out_of_range("Bounds check failed in sequence_container_interface::at()");
  755. return std::ranges::begin(derived())[n];
  756. }
  757. template<std::ranges::random_access_range C = const D>
  758. constexpr decltype(auto) at(v2_dtl::container_size_t<C> n) const {
  759. if (derived().size() <= n)
  760. throw std::out_of_range("Bounds check failed in sequence_container_interface::at()");
  761. return std::ranges::begin(derived())[n];
  762. }
  763. constexpr auto begin() const {
  764. return typename D::const_iterator(mutable_derived().begin());
  765. }
  766. constexpr auto end() const {
  767. return typename D::const_iterator(mutable_derived().end());
  768. }
  769. constexpr auto cbegin() const { return derived().begin(); }
  770. constexpr auto cend() const { return derived().end(); }
  771. constexpr auto rbegin()
  772. requires std::ranges::bidirectional_range<D> && std::ranges::common_range<D> {
  773. return std::reverse_iterator(std::ranges::end(derived()));
  774. }
  775. constexpr auto rend()
  776. requires std::ranges::bidirectional_range<D> && std::ranges::common_range<D> {
  777. return std::reverse_iterator(std::ranges::begin(derived()));
  778. }
  779. constexpr auto rbegin() const
  780. requires std::ranges::bidirectional_range<const D> &&
  781. std::ranges::common_range<const D> {
  782. return std::reverse_iterator(std::ranges::iterator_t<const D>(
  783. mutable_derived().end()));
  784. }
  785. constexpr auto rend() const
  786. requires std::ranges::bidirectional_range<const D> &&
  787. std::ranges::common_range<const D> {
  788. return std::reverse_iterator(std::ranges::iterator_t<const D>(
  789. mutable_derived().begin()));
  790. }
  791. constexpr auto crbegin() const
  792. requires std::ranges::bidirectional_range<const D> &&
  793. std::ranges::common_range<const D> {
  794. return std::reverse_iterator(std::ranges::iterator_t<const D>(
  795. mutable_derived().end()));
  796. }
  797. constexpr auto crend() const
  798. requires std::ranges::bidirectional_range<const D> &&
  799. std::ranges::common_range<const D> {
  800. return std::reverse_iterator(std::ranges::iterator_t<const D>(
  801. mutable_derived().begin()));
  802. }
  803. template<typename C = D>
  804. constexpr auto insert(std::ranges::iterator_t<const C> position,
  805. const std::ranges::range_value_t<C>& x)
  806. requires requires (D d) { d.emplace(position, x); } {
  807. return derived().emplace(position, x);
  808. }
  809. template<typename C = D>
  810. constexpr auto insert(std::ranges::iterator_t<const C> position,
  811. std::ranges::range_value_t<C>&& x)
  812. requires requires (D d) { d.emplace(position, std::move(x)); } {
  813. return derived().emplace(position, std::move(x));
  814. }
  815. template<typename C = D>
  816. constexpr auto insert(std::ranges::iterator_t<const C> position,
  817. v2_dtl::container_size_t<C> n,
  818. const std::ranges::range_value_t<C>& x)
  819. requires v2_dtl::range_insert<C, v2_dtl::n_iter_t<C>> {
  820. auto first = detail::make_n_iter(x, n);
  821. auto last = detail::make_n_iter_end(x, n);
  822. return derived().insert(
  823. position, detail::make_n_iter(x, n), detail::make_n_iter_end(x, n));
  824. }
  825. template<typename C = D>
  826. constexpr auto insert(std::ranges::iterator_t<const C> position,
  827. std::initializer_list<std::ranges::range_value_t<C>> il)
  828. requires requires (D d) {
  829. d.template insert<decltype(position), decltype(il)>(
  830. position, il.begin(), il.end()); } {
  831. return derived().insert(position, il.begin(), il.end());
  832. }
  833. template<typename C = D>
  834. constexpr void erase(typename C::const_iterator position)
  835. requires requires (D d) { d.erase(position, std::ranges::next(position)); } {
  836. derived().erase(position, std::ranges::next(position));
  837. }
  838. template<std::input_iterator Iter, typename C = D>
  839. constexpr void assign(Iter first, Iter last)
  840. requires requires (D d) {
  841. d.erase(std::ranges::begin(d), std::ranges::end(d));
  842. d.insert(std::ranges::begin(d), first, last); } {
  843. auto out = derived().begin();
  844. auto const out_last = derived().end();
  845. for (; out != out_last && first != last; ++first, ++out) {
  846. *out = *first;
  847. }
  848. if (out != out_last)
  849. derived().erase(out, out_last);
  850. if (first != last)
  851. derived().insert(derived().end(), first, last);
  852. }
  853. template<typename C = D>
  854. constexpr void assign(v2_dtl::container_size_t<C> n,
  855. const std::ranges::range_value_t<C>& x)
  856. requires requires (D d) {
  857. { d.size() } -> std::convertible_to<std::size_t>;
  858. d.erase(std::ranges::begin(d), std::ranges::end(d));
  859. d.insert(std::ranges::begin(d),
  860. detail::make_n_iter(x, n),
  861. detail::make_n_iter_end(x, n)); } {
  862. if (detail::fake_capacity(derived()) < n) {
  863. C temp(n, x);
  864. derived().swap(temp);
  865. } else {
  866. auto const min_size = std::min<std::ptrdiff_t>(n, derived().size());
  867. auto const fill_end = std::fill_n(derived().begin(), min_size, x);
  868. if (min_size < (std::ptrdiff_t)derived().size()) {
  869. derived().erase(fill_end, derived().end());
  870. } else {
  871. n -= min_size;
  872. derived().insert(
  873. derived().begin(),
  874. detail::make_n_iter(x, n),
  875. detail::make_n_iter_end(x, n));
  876. }
  877. }
  878. }
  879. template<typename C = D>
  880. constexpr void assign(std::initializer_list<std::ranges::range_value_t<C>> il)
  881. requires requires (D d) { d.assign(il.begin(), il.end()); } {
  882. derived().assign(il.begin(), il.end());
  883. }
  884. constexpr void clear() noexcept
  885. requires requires (D d) {
  886. d.erase(std::ranges::begin(d), std::ranges::end(d)); } {
  887. derived().erase(std::ranges::begin(derived()), std::ranges::end(derived()));
  888. }
  889. template<typename C = D>
  890. constexpr decltype(auto) operator=(
  891. std::initializer_list<std::ranges::range_value_t<C>> il)
  892. requires requires (D d) { d.assign(il.begin(), il.end()); } {
  893. derived().assign(il.begin(), il.end());
  894. return *this;
  895. }
  896. friend constexpr void swap(D& lhs, D& rhs) requires requires { lhs.swap(rhs); } {
  897. return lhs.swap(rhs);
  898. }
  899. friend constexpr bool operator==(const D& lhs, const D& rhs)
  900. requires std::ranges::sized_range<const D> &&
  901. requires { std::ranges::equal(lhs, rhs); } {
  902. return lhs.size() == rhs.size() && std::ranges::equal(lhs, rhs);
  903. }
  904. #if 0 // TODO: This appears to work, but as of this writing (and using GCC
  905. // 10), op<=> is not yet being used to evaluate op==, op<, etc.
  906. friend constexpr std::compare_three_way_result_t<std::ranges::range_reference_t<const D>>
  907. operator<=>(const D& lhs, const D& rhs)
  908. requires std::three_way_comparable<std::ranges::range_reference_t<const D>> {
  909. return std::lexicographical_compare_three_way(lhs.begin(), lhs.end(),
  910. rhs.begin(), rhs.end());
  911. }
  912. #else
  913. friend constexpr bool operator!=(const D& lhs, const D& rhs)
  914. requires requires { lhs == rhs; } {
  915. return !(lhs == rhs);
  916. }
  917. friend constexpr bool operator<(D lhs, D rhs)
  918. requires std::totally_ordered<std::ranges::range_reference_t<D>> {
  919. return std::ranges::lexicographical_compare(lhs, rhs);
  920. }
  921. friend constexpr bool operator<=(D lhs, D rhs)
  922. requires std::totally_ordered<std::ranges::range_reference_t<D>> {
  923. return lhs == rhs || lhs < rhs;
  924. }
  925. friend constexpr bool operator>(D lhs, D rhs)
  926. requires std::totally_ordered<std::ranges::range_reference_t<D>> {
  927. return !(lhs <= rhs);
  928. }
  929. friend constexpr bool operator>=(D lhs, D rhs)
  930. requires std::totally_ordered<std::ranges::range_reference_t<D>> {
  931. return rhs <= lhs;
  932. }
  933. #endif
  934. };
  935. // clang-format on
  936. }}}
  937. #endif
  938. #if defined(BOOST_STL_INTERFACES_DOXYGEN) || BOOST_STL_INTERFACES_USE_DEDUCED_THIS
  939. namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V3 {
  940. // TODO: Reimplement using deduced this.
  941. template<typename D,
  942. element_layout Contiguity = element_layout::discontiguous>
  943. using sequence_container_interface = v2::sequence_container_interface<D, Contiguity>;
  944. }}}
  945. #endif
  946. #endif