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