sequence_container_interface.hpp 40 KB

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