File indexing completed on 2024-11-15 09:32:19
0001
0002
0003
0004
0005
0006 #ifndef BOOST_STL_INTERFACES_CONTAINER_INTERFACE_HPP
0007 #define BOOST_STL_INTERFACES_CONTAINER_INTERFACE_HPP
0008
0009 #include <boost/stl_interfaces/reverse_iterator.hpp>
0010
0011 #include <boost/assert.hpp>
0012 #include <boost/config.hpp>
0013
0014 #include <algorithm>
0015 #include <stdexcept>
0016 #include <cstddef>
0017
0018
0019 namespace boost { namespace stl_interfaces { namespace detail {
0020
0021 template<typename T, typename SizeType>
0022 struct n_iter : iterator_interface<
0023 #if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS
0024 n_iter<T, SizeType>,
0025 #endif
0026 std::random_access_iterator_tag,
0027 T>
0028 {
0029 n_iter() : x_(nullptr), n_(0) {}
0030 n_iter(T const & x, SizeType n) : x_(&x), n_(n) {}
0031
0032 T const & operator*() const { return *x_; }
0033 constexpr std::ptrdiff_t operator-(n_iter other) const noexcept
0034 {
0035 return std::ptrdiff_t(n_) - std::ptrdiff_t(other.n_);
0036 }
0037 n_iter & operator+=(std::ptrdiff_t offset)
0038 {
0039 n_ += offset;
0040 return *this;
0041 }
0042
0043 private:
0044 T const * x_;
0045 SizeType n_;
0046 };
0047
0048 template<typename T, typename SizeType>
0049 constexpr auto make_n_iter(T const & x, SizeType n) noexcept(
0050 noexcept(n_iter<T, SizeType>(x, n)))
0051 {
0052 using result_type = n_iter<T, SizeType>;
0053 return result_type(x, SizeType(0));
0054 }
0055 template<typename T, typename SizeType>
0056 constexpr auto make_n_iter_end(T const & x, SizeType n) noexcept(
0057 noexcept(n_iter<T, SizeType>(x, n)))
0058 {
0059 return n_iter<T, SizeType>(x, n);
0060 }
0061
0062 template<typename Container>
0063 std::size_t fake_capacity(Container const & c)
0064 {
0065 return SIZE_MAX;
0066 }
0067 template<
0068 typename Container,
0069 typename Enable = decltype(
0070 std::size_t() = std::declval<Container const &>().capacity())>
0071 std::size_t fake_capacity(Container const & c)
0072 {
0073 return c.capacity();
0074 }
0075
0076 }}}
0077
0078 namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V1 {
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097 template<
0098 typename Derived,
0099 element_layout Contiguity = element_layout::discontiguous
0100 #ifndef BOOST_STL_INTERFACES_DOXYGEN
0101 ,
0102 typename E = std::enable_if_t<
0103 std::is_class<Derived>::value &&
0104 std::is_same<Derived, std::remove_cv_t<Derived>>::value>
0105 #endif
0106 >
0107 struct sequence_container_interface;
0108
0109 namespace v1_dtl {
0110 template<typename Iter>
0111 using in_iter = std::is_convertible<
0112 typename std::iterator_traits<Iter>::iterator_category,
0113 std::input_iterator_tag>;
0114
0115 template<typename D, typename = void>
0116 struct clear_impl
0117 {
0118 static constexpr void call(D & d) noexcept {}
0119 };
0120 template<typename D>
0121 struct clear_impl<D, void_t<decltype(std::declval<D>().clear())>>
0122 {
0123 static constexpr void call(D & d) noexcept { d.clear(); }
0124 };
0125
0126 template<typename D, element_layout Contiguity>
0127 void derived_container(sequence_container_interface<D, Contiguity> const &);
0128 }
0129
0130 template<
0131 typename Derived,
0132 element_layout Contiguity
0133 #ifndef BOOST_STL_INTERFACES_DOXYGEN
0134 ,
0135 typename E
0136 #endif
0137 >
0138 struct sequence_container_interface
0139 {
0140 #ifndef BOOST_STL_INTERFACES_DOXYGEN
0141 private:
0142 constexpr Derived & derived() noexcept
0143 {
0144 return static_cast<Derived &>(*this);
0145 }
0146 constexpr const Derived & derived() const noexcept
0147 {
0148 return static_cast<Derived const &>(*this);
0149 }
0150 constexpr Derived & mutable_derived() const noexcept
0151 {
0152 return const_cast<Derived &>(static_cast<Derived const &>(*this));
0153 }
0154 #endif
0155
0156 public:
0157 template<typename D = Derived>
0158 constexpr auto empty() noexcept(
0159 noexcept(std::declval<D &>().begin() == std::declval<D &>().end()))
0160 -> decltype(
0161 std::declval<D &>().begin() == std::declval<D &>().end())
0162 {
0163 return derived().begin() == derived().end();
0164 }
0165 template<typename D = Derived>
0166 constexpr auto empty() const noexcept(noexcept(
0167 std::declval<D const &>().begin() ==
0168 std::declval<D const &>().end()))
0169 -> decltype(
0170 std::declval<D const &>().begin() ==
0171 std::declval<D const &>().end())
0172 {
0173 return derived().begin() == derived().end();
0174 }
0175
0176 template<
0177 typename D = Derived,
0178 element_layout C = Contiguity,
0179 typename Enable = std::enable_if_t<C == element_layout::contiguous>>
0180 constexpr auto data() noexcept(noexcept(std::declval<D &>().begin()))
0181 -> decltype(std::addressof(*std::declval<D &>().begin()))
0182 {
0183 return std::addressof(*derived().begin());
0184 }
0185 template<
0186 typename D = Derived,
0187 element_layout C = Contiguity,
0188 typename Enable = std::enable_if_t<C == element_layout::contiguous>>
0189 constexpr auto data() const
0190 noexcept(noexcept(std::declval<D const &>().begin()))
0191 -> decltype(std::addressof(*std::declval<D const &>().begin()))
0192 {
0193 return std::addressof(*derived().begin());
0194 }
0195
0196 template<typename D = Derived>
0197 constexpr auto size()
0198 #if !BOOST_CLANG
0199 noexcept(noexcept(
0200 std::declval<D &>().end() - std::declval<D &>().begin()))
0201 #endif
0202 -> decltype(typename D::size_type(
0203 std::declval<D &>().end() - std::declval<D &>().begin()))
0204 {
0205 return derived().end() - derived().begin();
0206 }
0207 template<typename D = Derived>
0208 constexpr auto size() const noexcept(noexcept(
0209 std::declval<D const &>().end() -
0210 std::declval<D const &>().begin()))
0211 -> decltype(typename D::size_type(
0212 #if !BOOST_CLANG
0213 std::declval<D const &>().end() -
0214 std::declval<D const &>().begin()
0215 #endif
0216 ))
0217 {
0218 return derived().end() - derived().begin();
0219 }
0220
0221 template<typename D = Derived>
0222 constexpr auto front() noexcept(noexcept(*std::declval<D &>().begin()))
0223 -> decltype(*std::declval<D &>().begin())
0224 {
0225 return *derived().begin();
0226 }
0227 template<typename D = Derived>
0228 constexpr auto front() const
0229 noexcept(noexcept(*std::declval<D const &>().begin()))
0230 -> decltype(*std::declval<D const &>().begin())
0231 {
0232 return *derived().begin();
0233 }
0234
0235 template<typename D = Derived>
0236 constexpr auto push_front(typename D::value_type const & x) noexcept(
0237 noexcept(std::declval<D &>().emplace_front(x)))
0238 -> decltype((void)std::declval<D &>().emplace_front(x))
0239 {
0240 derived().emplace_front(x);
0241 }
0242
0243 template<typename D = Derived>
0244 constexpr auto push_front(typename D::value_type && x) noexcept(
0245 noexcept(std::declval<D &>().emplace_front(std::move(x))))
0246 -> decltype((void)std::declval<D &>().emplace_front(std::move(x)))
0247 {
0248 derived().emplace_front(std::move(x));
0249 }
0250
0251 template<typename D = Derived>
0252 constexpr auto pop_front() noexcept -> decltype(
0253 std::declval<D &>().emplace_front(
0254 std::declval<typename D::value_type &>()),
0255 (void)std::declval<D &>().erase(std::declval<D &>().begin()))
0256 {
0257 derived().erase(derived().begin());
0258 }
0259
0260 template<
0261 typename D = Derived,
0262 typename Enable = std::enable_if_t<
0263 v1_dtl::decrementable_sentinel<D>::value &&
0264 v1_dtl::common_range<D>::value>>
0265 constexpr auto
0266 back() noexcept(noexcept(*std::prev(std::declval<D &>().end())))
0267 -> decltype(*std::prev(std::declval<D &>().end()))
0268 {
0269 return *std::prev(derived().end());
0270 }
0271 template<
0272 typename D = Derived,
0273 typename Enable = std::enable_if_t<
0274 v1_dtl::decrementable_sentinel<D>::value &&
0275 v1_dtl::common_range<D>::value>>
0276 constexpr auto back() const
0277 noexcept(noexcept(*std::prev(std::declval<D const &>().end())))
0278 -> decltype(*std::prev(std::declval<D const &>().end()))
0279 {
0280 return *std::prev(derived().end());
0281 }
0282
0283 template<typename D = Derived>
0284 constexpr auto push_back(typename D::value_type const & x) noexcept(
0285 noexcept(std::declval<D &>().emplace_back(x)))
0286 -> decltype((void)std::declval<D &>().emplace_back(x))
0287 {
0288 derived().emplace_back(x);
0289 }
0290
0291 template<typename D = Derived>
0292 constexpr auto push_back(typename D::value_type && x) noexcept(
0293 noexcept(std::declval<D &>().emplace_back(std::move(x))))
0294 -> decltype((void)std::declval<D &>().emplace_back(std::move(x)))
0295 {
0296 derived().emplace_back(std::move(x));
0297 }
0298
0299 template<typename D = Derived>
0300 constexpr auto pop_back() noexcept -> decltype(
0301 std::declval<D &>().emplace_back(
0302 std::declval<typename D::value_type>()),
0303 (void)std::declval<D &>().erase(
0304 std::prev(std::declval<D &>().end())))
0305 {
0306 derived().erase(std::prev(derived().end()));
0307 }
0308
0309 template<typename D = Derived>
0310 constexpr auto operator[](typename D::size_type n) noexcept(
0311 noexcept(std::declval<D &>().begin()[n]))
0312 -> decltype(std::declval<D &>().begin()[n])
0313 {
0314 return derived().begin()[n];
0315 }
0316 template<typename D = Derived>
0317 constexpr auto operator[](typename D::size_type n) const
0318 noexcept(noexcept(std::declval<D const &>().begin()[n]))
0319 -> decltype(std::declval<D const &>().begin()[n])
0320 {
0321 return derived().begin()[n];
0322 }
0323
0324 template<typename D = Derived>
0325 constexpr auto at(typename D::size_type i)
0326 -> decltype(std::declval<D &>().size(), std::declval<D &>()[i])
0327 {
0328 if (derived().size() <= i) {
0329 throw std::out_of_range(
0330 "Bounds check failed in sequence_container_interface::at()");
0331 }
0332 return derived()[i];
0333 }
0334
0335 template<typename D = Derived>
0336 constexpr auto at(typename D::size_type i) const -> decltype(
0337 std::declval<D const &>().size(), std::declval<D const &>()[i])
0338 {
0339 if (derived().size() <= i) {
0340 throw std::out_of_range(
0341 "Bounds check failed in sequence_container_interface::at()");
0342 }
0343 return derived()[i];
0344 }
0345
0346 template<typename D = Derived, typename Iter = typename D::const_iterator>
0347 constexpr Iter begin() const
0348 noexcept(noexcept(std::declval<D &>().begin()))
0349 {
0350 return Iter(mutable_derived().begin());
0351 }
0352 template<typename D = Derived, typename Iter = typename D::const_iterator>
0353 constexpr Iter end() const noexcept(noexcept(std::declval<D &>().end()))
0354 {
0355 return Iter(mutable_derived().end());
0356 }
0357
0358 template<typename D = Derived>
0359 constexpr auto cbegin() const
0360 noexcept(noexcept(std::declval<D const &>().begin()))
0361 -> decltype(std::declval<D const &>().begin())
0362 {
0363 return derived().begin();
0364 }
0365 template<typename D = Derived>
0366 constexpr auto cend() const
0367 noexcept(noexcept(std::declval<D const &>().end()))
0368 -> decltype(std::declval<D const &>().end())
0369 {
0370 return derived().end();
0371 }
0372
0373 template<
0374 typename D = Derived,
0375 typename Enable = std::enable_if_t<v1_dtl::common_range<D>::value>>
0376 constexpr auto rbegin() noexcept(noexcept(
0377 stl_interfaces::make_reverse_iterator(std::declval<D &>().end())))
0378 {
0379 return stl_interfaces::make_reverse_iterator(derived().end());
0380 }
0381 template<
0382 typename D = Derived,
0383 typename Enable = std::enable_if_t<v1_dtl::common_range<D>::value>>
0384 constexpr auto rend() noexcept(noexcept(
0385 stl_interfaces::make_reverse_iterator(std::declval<D &>().begin())))
0386 {
0387 return stl_interfaces::make_reverse_iterator(derived().begin());
0388 }
0389
0390 template<typename D = Derived>
0391 constexpr auto rbegin() const
0392 noexcept(noexcept(std::declval<D &>().rbegin()))
0393 {
0394 return
0395 typename D::const_reverse_iterator(mutable_derived().rbegin());
0396 }
0397 template<typename D = Derived>
0398 constexpr auto rend() const
0399 noexcept(noexcept(std::declval<D &>().rend()))
0400 {
0401 return typename D::const_reverse_iterator(mutable_derived().rend());
0402 }
0403
0404 template<typename D = Derived>
0405 constexpr auto crbegin() const
0406 noexcept(noexcept(std::declval<D const &>().rbegin()))
0407 -> decltype(std::declval<D const &>().rbegin())
0408 {
0409 return derived().rbegin();
0410 }
0411 template<typename D = Derived>
0412 constexpr auto crend() const
0413 noexcept(noexcept(std::declval<D const &>().rend()))
0414 -> decltype(std::declval<D const &>().rend())
0415 {
0416 return derived().rend();
0417 }
0418
0419 template<typename D = Derived>
0420 constexpr auto insert(
0421 typename D::const_iterator pos,
0422 typename D::value_type const &
0423 x) noexcept(noexcept(std::declval<D &>().emplace(pos, x)))
0424 -> decltype(std::declval<D &>().emplace(pos, x))
0425 {
0426 return derived().emplace(pos, x);
0427 }
0428
0429 template<typename D = Derived>
0430 constexpr auto insert(
0431 typename D::const_iterator pos,
0432 typename D::value_type &&
0433 x) noexcept(noexcept(std::declval<D &>()
0434 .emplace(pos, std::move(x))))
0435 -> decltype(std::declval<D &>().emplace(pos, std::move(x)))
0436 {
0437 return derived().emplace(pos, std::move(x));
0438 }
0439
0440 template<typename D = Derived>
0441 constexpr auto insert(
0442 typename D::const_iterator pos,
0443 typename D::size_type n,
0444 typename D::value_type const & x)
0445
0446
0447
0448
0449
0450
0451
0452
0453 noexcept(noexcept(std::declval<D &>().insert(
0454 pos, detail::make_n_iter(x, n), detail::make_n_iter_end(x, n))))
0455
0456
0457
0458 #if 0
0459 -> decltype(std::declval<D &>().insert(
0460 pos, detail::make_n_iter(x, n), detail::make_n_iter_end(x, n)))
0461 #endif
0462 {
0463 return derived().insert(
0464 pos, detail::make_n_iter(x, n), detail::make_n_iter_end(x, n));
0465 }
0466
0467 template<typename D = Derived>
0468 constexpr auto insert(
0469 typename D::const_iterator pos,
0470 std::initializer_list<typename D::value_type>
0471 il) noexcept(noexcept(std::declval<D &>()
0472 .insert(pos, il.begin(), il.end())))
0473 -> decltype(std::declval<D &>().insert(pos, il.begin(), il.end()))
0474 {
0475 return derived().insert(pos, il.begin(), il.end());
0476 }
0477
0478 template<typename D = Derived>
0479 constexpr auto erase(typename D::const_iterator pos) noexcept
0480 -> decltype(std::declval<D &>().erase(pos, std::next(pos)))
0481 {
0482 return derived().erase(pos, std::next(pos));
0483 }
0484
0485 template<
0486 typename InputIterator,
0487 typename D = Derived,
0488 typename Enable =
0489 std::enable_if_t<v1_dtl::in_iter<InputIterator>::value>>
0490 constexpr auto assign(InputIterator first, InputIterator last) noexcept(
0491 noexcept(std::declval<D &>().insert(
0492 std::declval<D &>().begin(), first, last)))
0493 -> decltype(
0494 std::declval<D &>().erase(
0495 std::declval<D &>().begin(), std::declval<D &>().end()),
0496 (void)std::declval<D &>().insert(
0497 std::declval<D &>().begin(), first, last))
0498 {
0499 auto out = derived().begin();
0500 auto const out_last = derived().end();
0501 for (; out != out_last && first != last; ++first, ++out) {
0502 *out = *first;
0503 }
0504 if (out != out_last)
0505 derived().erase(out, out_last);
0506 if (first != last)
0507 derived().insert(derived().end(), first, last);
0508 }
0509
0510 template<typename D = Derived>
0511 constexpr auto assign(
0512 typename D::size_type n,
0513 typename D::value_type const &
0514 x) noexcept(noexcept(std::declval<D &>()
0515 .insert(
0516 std::declval<D &>().begin(),
0517 detail::make_n_iter(x, n),
0518 detail::make_n_iter_end(x, n))))
0519 -> decltype(
0520 std::declval<D &>().size(),
0521 std::declval<D &>().erase(
0522 std::declval<D &>().begin(), std::declval<D &>().end()),
0523 (void)std::declval<D &>().insert(
0524 std::declval<D &>().begin(),
0525 detail::make_n_iter(x, n),
0526 detail::make_n_iter_end(x, n)))
0527 {
0528 if (detail::fake_capacity(derived()) < n) {
0529 Derived temp(n, x);
0530 derived().swap(temp);
0531 } else {
0532 auto const min_size =
0533 std::min<std::ptrdiff_t>(n, derived().size());
0534 auto const fill_end =
0535 std::fill_n(derived().begin(), min_size, x);
0536 if (min_size < (std::ptrdiff_t)derived().size()) {
0537 derived().erase(fill_end, derived().end());
0538 } else {
0539 n -= min_size;
0540 derived().insert(
0541 derived().begin(),
0542 detail::make_n_iter(x, n),
0543 detail::make_n_iter_end(x, n));
0544 }
0545 }
0546 }
0547
0548 template<typename D = Derived>
0549 constexpr auto
0550 assign(std::initializer_list<typename D::value_type> il) noexcept(
0551 noexcept(std::declval<D &>().assign(il.begin(), il.end())))
0552 -> decltype((void)std::declval<D &>().assign(il.begin(), il.end()))
0553 {
0554 derived().assign(il.begin(), il.end());
0555 }
0556
0557 template<typename D = Derived>
0558 constexpr auto
0559 operator=(std::initializer_list<typename D::value_type> il) noexcept(
0560 noexcept(std::declval<D &>().assign(il.begin(), il.end())))
0561 -> decltype(
0562 std::declval<D &>().assign(il.begin(), il.end()),
0563 std::declval<D &>())
0564 {
0565 derived().assign(il.begin(), il.end());
0566 return *this;
0567 }
0568
0569 template<typename D = Derived>
0570 constexpr auto clear() noexcept
0571 -> decltype((void)std::declval<D &>().erase(
0572 std::declval<D &>().begin(), std::declval<D &>().end()))
0573 {
0574 derived().erase(derived().begin(), derived().end());
0575 }
0576 };
0577
0578
0579
0580 template<typename ContainerInterface>
0581 constexpr auto swap(
0582 ContainerInterface & lhs,
0583 ContainerInterface & rhs) noexcept(noexcept(lhs.swap(rhs)))
0584 -> decltype(v1_dtl::derived_container(lhs), lhs.swap(rhs))
0585 {
0586 return lhs.swap(rhs);
0587 }
0588
0589
0590
0591 template<typename ContainerInterface>
0592 constexpr auto
0593 operator==(ContainerInterface const & lhs, ContainerInterface const & rhs) noexcept(
0594 noexcept(lhs.size() == rhs.size()) &&
0595 noexcept(*lhs.begin() == *rhs.begin()))
0596 -> decltype(
0597 v1_dtl::derived_container(lhs),
0598 lhs.size() == rhs.size(),
0599 *lhs.begin() == *rhs.begin(),
0600 true)
0601 {
0602 return lhs.size() == rhs.size() &&
0603 std::equal(lhs.begin(), lhs.end(), rhs.begin());
0604 }
0605
0606
0607
0608 template<typename ContainerInterface>
0609 constexpr auto operator!=(
0610 ContainerInterface const & lhs,
0611 ContainerInterface const & rhs) noexcept(noexcept(lhs == rhs))
0612 -> decltype(v1_dtl::derived_container(lhs), lhs == rhs)
0613 {
0614 return !(lhs == rhs);
0615 }
0616
0617
0618
0619 template<typename ContainerInterface>
0620 constexpr auto operator<(
0621 ContainerInterface const & lhs,
0622 ContainerInterface const &
0623 rhs) noexcept(noexcept(*lhs.begin() < *rhs.begin()))
0624 -> decltype(
0625 v1_dtl::derived_container(lhs), *lhs.begin() < *rhs.begin(), true)
0626 {
0627 auto it1 = lhs.begin();
0628 auto const last1 = lhs.end();
0629 auto it2 = rhs.begin();
0630 auto const last2 = rhs.end();
0631 for (; it1 != last1 && it2 != last2; ++it1, ++it2) {
0632 if (*it1 < *it2)
0633 return true;
0634 if (*it2 < *it1)
0635 return false;
0636 }
0637 return it1 == last1 && it2 != last2;
0638 }
0639
0640
0641
0642 template<typename ContainerInterface>
0643 constexpr auto operator<=(
0644 ContainerInterface const & lhs,
0645 ContainerInterface const & rhs) noexcept(noexcept(lhs < rhs))
0646 -> decltype(v1_dtl::derived_container(lhs), lhs < rhs)
0647 {
0648 return !(rhs < lhs);
0649 }
0650
0651
0652
0653 template<typename ContainerInterface>
0654 constexpr auto operator>(
0655 ContainerInterface const & lhs,
0656 ContainerInterface const & rhs) noexcept(noexcept(lhs < rhs))
0657 -> decltype(v1_dtl::derived_container(lhs), lhs < rhs)
0658 {
0659 return rhs < lhs;
0660 }
0661
0662
0663
0664 template<typename ContainerInterface>
0665 constexpr auto operator>=(
0666 ContainerInterface const & lhs,
0667 ContainerInterface const & rhs) noexcept(noexcept(lhs < rhs))
0668 -> decltype(v1_dtl::derived_container(lhs), lhs < rhs)
0669 {
0670 return !(lhs < rhs);
0671 }
0672
0673 }}}
0674
0675 #if defined(BOOST_STL_INTERFACES_DOXYGEN) || BOOST_STL_INTERFACES_USE_CONCEPTS
0676
0677 namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V2 {
0678
0679 namespace v2_dtl {
0680
0681
0682
0683 template<typename T>
0684 using container_size_t = typename T::size_type;
0685
0686 template<typename T, typename I>
0687
0688 concept range_insert =
0689 requires (T t, std::ranges::iterator_t<T> t_it, I it) {
0690 t.template insert<I>(t_it, it, it);
0691
0692 };
0693
0694 template<typename T>
0695 using n_iter_t =
0696 detail::n_iter<std::ranges::range_value_t<T>, container_size_t<T>>;
0697 }
0698
0699
0700
0701
0702
0703
0704
0705
0706
0707
0708
0709
0710
0711
0712
0713
0714
0715
0716
0717
0718
0719
0720
0721
0722 template<typename D,
0723 element_layout Contiguity = element_layout::discontiguous>
0724 requires std::is_class_v<D> && std::same_as<D, std::remove_cv_t<D>>
0725 struct sequence_container_interface
0726 {
0727 private:
0728 constexpr D& derived() noexcept {
0729 return static_cast<D&>(*this);
0730 }
0731 constexpr const D& derived() const noexcept {
0732 return static_cast<const D&>(*this);
0733 }
0734 constexpr D & mutable_derived() const noexcept {
0735 return const_cast<D&>(static_cast<const D&>(*this));
0736 }
0737 static constexpr void clear_impl(D& d) noexcept {}
0738 static constexpr void clear_impl(D& d) noexcept
0739 requires requires { d.clear(); }
0740 { d.clear(); }
0741
0742 public:
0743 constexpr bool empty() const {
0744 return std::ranges::begin(derived()) == std::ranges::end(derived());
0745 }
0746
0747 constexpr auto data() requires std::contiguous_iterator<std::ranges::iterator_t<D>> {
0748 return std::to_address(std::ranges::begin(derived()));
0749 }
0750 constexpr auto data() const requires std::contiguous_iterator<std::ranges::iterator_t<const D>> {
0751 return std::to_address(std::ranges::begin(derived()));
0752 }
0753
0754 template<typename C = D>
0755 constexpr v2_dtl::container_size_t<C> size() const
0756 requires std::sized_sentinel_for<std::ranges::sentinel_t<const C>, std::ranges::iterator_t<const C>> {
0757 return v2_dtl::container_size_t<C>(
0758 std::ranges::end(derived()) - std::ranges::begin(derived()));
0759 }
0760
0761 constexpr decltype(auto) front() {
0762 BOOST_ASSERT(!empty());
0763 return *std::ranges::begin(derived());
0764 }
0765 constexpr decltype(auto) front() const {
0766 BOOST_ASSERT(!empty());
0767 return *std::ranges::begin(derived());
0768 }
0769
0770 template<typename C = D>
0771 constexpr void push_front(const std::ranges::range_value_t<C>& x)
0772 requires requires (D d) { d.emplace_front(x); } {
0773 derived().emplace_front(x);
0774 }
0775 template<typename C = D>
0776 constexpr void push_front(std::ranges::range_value_t<C>&& x)
0777 requires requires (D d) { d.emplace_front(std::move(x)); } {
0778 derived().emplace_front(std::move(x));
0779 }
0780 constexpr void pop_front() noexcept
0781 requires requires (D d, const std::ranges::range_value_t<D>& x, std::ranges::iterator_t<D> position) {
0782 d.emplace_front(x);
0783 d.erase(position);
0784 } {
0785 return derived().erase(std::ranges::begin(derived()));
0786 }
0787
0788 constexpr decltype(auto) back()
0789 requires std::ranges::bidirectional_range<D> && std::ranges::common_range<D> {
0790 BOOST_ASSERT(!empty());
0791 return *std::ranges::prev(std::ranges::end(derived()));
0792 }
0793 constexpr decltype(auto) back() const
0794 requires std::ranges::bidirectional_range<const D> && std::ranges::common_range<const D> {
0795 BOOST_ASSERT(!empty());
0796 return *std::ranges::prev(std::ranges::end(derived()));
0797 }
0798
0799 template<std::ranges::bidirectional_range C = D>
0800 constexpr void push_back(const std::ranges::range_value_t<C>& x)
0801 requires std::ranges::common_range<C> && requires (D d) { d.emplace_back(x); } {
0802 derived().emplace_back(x);
0803 }
0804 template<std::ranges::bidirectional_range C = D>
0805 constexpr void push_back(std::ranges::range_value_t<C>&& x)
0806 requires std::ranges::common_range<C> && requires (D d) { d.emplace_back(std::move(x)); } {
0807 derived().emplace_back(std::move(x));
0808 }
0809 constexpr void pop_back() noexcept
0810 requires std::ranges::bidirectional_range<D> && std::ranges::common_range<D> &&
0811 requires (D d, std::ranges::range_value_t<D> x, std::ranges::iterator_t<D> position) {
0812 d.emplace_back(std::move(x));
0813 d.erase(position);
0814 } {
0815 return derived().erase(std::ranges::prev(std::ranges::end(derived())));
0816 }
0817
0818 template<std::ranges::random_access_range C = D>
0819 constexpr decltype(auto) operator[](v2_dtl::container_size_t<C> n) {
0820 return std::ranges::begin(derived())[n];
0821 }
0822 template<std::ranges::random_access_range C = const D>
0823 constexpr decltype(auto) operator[](v2_dtl::container_size_t<C> n) const {
0824 return std::ranges::begin(derived())[n];
0825 }
0826
0827 template<std::ranges::random_access_range C = D>
0828 constexpr decltype(auto) at(v2_dtl::container_size_t<C> n) {
0829 if (derived().size() <= n)
0830 throw std::out_of_range("Bounds check failed in sequence_container_interface::at()");
0831 return std::ranges::begin(derived())[n];
0832 }
0833 template<std::ranges::random_access_range C = const D>
0834 constexpr decltype(auto) at(v2_dtl::container_size_t<C> n) const {
0835 if (derived().size() <= n)
0836 throw std::out_of_range("Bounds check failed in sequence_container_interface::at()");
0837 return std::ranges::begin(derived())[n];
0838 }
0839
0840 constexpr auto begin() const {
0841 return typename D::const_iterator(mutable_derived().begin());
0842 }
0843 constexpr auto end() const {
0844 return typename D::const_iterator(mutable_derived().end());
0845 }
0846
0847 constexpr auto cbegin() const { return derived().begin(); }
0848 constexpr auto cend() const { return derived().end(); }
0849
0850 constexpr auto rbegin()
0851 requires std::ranges::bidirectional_range<D> && std::ranges::common_range<D> {
0852 return std::reverse_iterator(std::ranges::end(derived()));
0853 }
0854 constexpr auto rend()
0855 requires std::ranges::bidirectional_range<D> && std::ranges::common_range<D> {
0856 return std::reverse_iterator(std::ranges::begin(derived()));
0857 }
0858
0859 constexpr auto rbegin() const
0860 requires std::ranges::bidirectional_range<const D> &&
0861 std::ranges::common_range<const D> {
0862 return std::reverse_iterator(std::ranges::iterator_t<const D>(
0863 mutable_derived().end()));
0864 }
0865 constexpr auto rend() const
0866 requires std::ranges::bidirectional_range<const D> &&
0867 std::ranges::common_range<const D> {
0868 return std::reverse_iterator(std::ranges::iterator_t<const D>(
0869 mutable_derived().begin()));
0870 }
0871
0872 constexpr auto crbegin() const
0873 requires std::ranges::bidirectional_range<const D> &&
0874 std::ranges::common_range<const D> {
0875 return std::reverse_iterator(std::ranges::iterator_t<const D>(
0876 mutable_derived().end()));
0877 }
0878 constexpr auto crend() const
0879 requires std::ranges::bidirectional_range<const D> &&
0880 std::ranges::common_range<const D> {
0881 return std::reverse_iterator(std::ranges::iterator_t<const D>(
0882 mutable_derived().begin()));
0883 }
0884
0885 template<typename C = D>
0886 constexpr auto insert(std::ranges::iterator_t<const C> position,
0887 const std::ranges::range_value_t<C>& x)
0888 requires requires (D d) { d.emplace(position, x); } {
0889 return derived().emplace(position, x);
0890 }
0891 template<typename C = D>
0892 constexpr auto insert(std::ranges::iterator_t<const C> position,
0893 std::ranges::range_value_t<C>&& x)
0894 requires requires (D d) { d.emplace(position, std::move(x)); } {
0895 return derived().emplace(position, std::move(x));
0896 }
0897 template<typename C = D>
0898 constexpr auto insert(std::ranges::iterator_t<const C> position,
0899 v2_dtl::container_size_t<C> n,
0900 const std::ranges::range_value_t<C>& x)
0901 requires v2_dtl::range_insert<C, v2_dtl::n_iter_t<C>> {
0902 auto first = detail::make_n_iter(x, n);
0903 auto last = detail::make_n_iter_end(x, n);
0904 return derived().insert(
0905 position, detail::make_n_iter(x, n), detail::make_n_iter_end(x, n));
0906 }
0907 template<typename C = D>
0908 constexpr auto insert(std::ranges::iterator_t<const C> position,
0909 std::initializer_list<std::ranges::range_value_t<C>> il)
0910 requires requires (D d) {
0911 d.template insert<decltype(position), decltype(il)>(
0912 position, il.begin(), il.end()); } {
0913 return derived().insert(position, il.begin(), il.end());
0914 }
0915
0916 template<typename C = D>
0917 constexpr void erase(typename C::const_iterator position)
0918 requires requires (D d) { d.erase(position, std::ranges::next(position)); } {
0919 derived().erase(position, std::ranges::next(position));
0920 }
0921
0922 template<std::input_iterator Iter, typename C = D>
0923 constexpr void assign(Iter first, Iter last)
0924 requires requires (D d) {
0925 d.erase(std::ranges::begin(d), std::ranges::end(d));
0926 d.insert(std::ranges::begin(d), first, last); } {
0927 auto out = derived().begin();
0928 auto const out_last = derived().end();
0929 for (; out != out_last && first != last; ++first, ++out) {
0930 *out = *first;
0931 }
0932 if (out != out_last)
0933 derived().erase(out, out_last);
0934 if (first != last)
0935 derived().insert(derived().end(), first, last);
0936 }
0937 template<typename C = D>
0938 constexpr void assign(v2_dtl::container_size_t<C> n,
0939 const std::ranges::range_value_t<C>& x)
0940 requires requires (D d) {
0941 { d.size() } -> std::convertible_to<std::size_t>;
0942 d.erase(std::ranges::begin(d), std::ranges::end(d));
0943 d.insert(std::ranges::begin(d),
0944 detail::make_n_iter(x, n),
0945 detail::make_n_iter_end(x, n)); } {
0946 if (detail::fake_capacity(derived()) < n) {
0947 C temp(n, x);
0948 derived().swap(temp);
0949 } else {
0950 auto const min_size = std::min<std::ptrdiff_t>(n, derived().size());
0951 auto const fill_end = std::fill_n(derived().begin(), min_size, x);
0952 if (min_size < (std::ptrdiff_t)derived().size()) {
0953 derived().erase(fill_end, derived().end());
0954 } else {
0955 n -= min_size;
0956 derived().insert(
0957 derived().begin(),
0958 detail::make_n_iter(x, n),
0959 detail::make_n_iter_end(x, n));
0960 }
0961 }
0962 }
0963 template<typename C = D>
0964 constexpr void assign(std::initializer_list<std::ranges::range_value_t<C>> il)
0965 requires requires (D d) { d.assign(il.begin(), il.end()); } {
0966 derived().assign(il.begin(), il.end());
0967 }
0968
0969 constexpr void clear() noexcept
0970 requires requires (D d) {
0971 d.erase(std::ranges::begin(d), std::ranges::end(d)); } {
0972 derived().erase(std::ranges::begin(derived()), std::ranges::end(derived()));
0973 }
0974
0975 template<typename C = D>
0976 constexpr decltype(auto) operator=(
0977 std::initializer_list<std::ranges::range_value_t<C>> il)
0978 requires requires (D d) { d.assign(il.begin(), il.end()); } {
0979 derived().assign(il.begin(), il.end());
0980 return *this;
0981 }
0982
0983 friend constexpr void swap(D& lhs, D& rhs) requires requires { lhs.swap(rhs); } {
0984 return lhs.swap(rhs);
0985 }
0986
0987 friend constexpr bool operator==(const D& lhs, const D& rhs)
0988 requires std::ranges::sized_range<const D> &&
0989 requires { std::ranges::equal(lhs, rhs); } {
0990 return lhs.size() == rhs.size() && std::ranges::equal(lhs, rhs);
0991 }
0992 #if 0
0993
0994 friend constexpr std::compare_three_way_result_t<std::ranges::range_reference_t<const D>>
0995 operator<=>(const D& lhs, const D& rhs)
0996 requires std::three_way_comparable<std::ranges::range_reference_t<const D>> {
0997 return std::lexicographical_compare_three_way(lhs.begin(), lhs.end(),
0998 rhs.begin(), rhs.end());
0999 }
1000 #else
1001 friend constexpr bool operator!=(const D& lhs, const D& rhs)
1002 requires requires { lhs == rhs; } {
1003 return !(lhs == rhs);
1004 }
1005 friend constexpr bool operator<(D lhs, D rhs)
1006 requires std::totally_ordered<std::ranges::range_reference_t<D>> {
1007 return std::ranges::lexicographical_compare(lhs, rhs);
1008 }
1009 friend constexpr bool operator<=(D lhs, D rhs)
1010 requires std::totally_ordered<std::ranges::range_reference_t<D>> {
1011 return lhs == rhs || lhs < rhs;
1012 }
1013 friend constexpr bool operator>(D lhs, D rhs)
1014 requires std::totally_ordered<std::ranges::range_reference_t<D>> {
1015 return !(lhs <= rhs);
1016 }
1017 friend constexpr bool operator>=(D lhs, D rhs)
1018 requires std::totally_ordered<std::ranges::range_reference_t<D>> {
1019 return rhs <= lhs;
1020 }
1021 #endif
1022 };
1023
1024
1025
1026 }}}
1027
1028 #endif
1029
1030 #if defined(BOOST_STL_INTERFACES_DOXYGEN) || BOOST_STL_INTERFACES_USE_DEDUCED_THIS
1031
1032 namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V3 {
1033
1034
1035 template<typename D,
1036 element_layout Contiguity = element_layout::discontiguous>
1037 using sequence_container_interface = v2::sequence_container_interface<D, Contiguity>;
1038
1039 }}}
1040
1041 #endif
1042
1043 #endif