33#ifndef BEMAN_INPLACE_VECTOR_INPLACE_VECTOR_HPP
44#define BEMAN_INPLACE_VECTOR_INPLACE_VECTOR_HPP
55
6+ #if !defined(__has_include) || __has_include(<beman/inplace_vector/config.hpp>)
67#include < beman/inplace_vector/config.hpp>
8+ #endif
79
810#include < algorithm> // for rotate...
911#include < array>
1214#include < cstddef> // for size_t
1315#include < cstdint> // for fixed-width integer types
1416#include < cstdio> // for assertion diagnostics
15- #include < cstdlib> // for abort
1617#include < functional> // for less and equal_to
1718#include < iterator> // for reverse_iterator and iterator traits
1819#include < limits> // for numeric_limits
1920#include < memory> // for destroy
2021#include < new> // for operator new
2122#include < ranges>
22- #include < stdexcept> // for length_error
2323#include < type_traits> // for aligned_storage and all meta-functions
2424
2525// Artifact from previous implementation, can be used as hints for optimizer
3131#define BEMAN_IV_FREESTANDING_DELETE (impl ) impl
3232#endif
3333
34+ #ifndef BEMAN_IV_THROW_OR_ABORT
35+ #if BEMAN_INPLACE_VECTOR_NO_EXCEPTIONS()
36+ #include < cstdlib> // for abort
37+ #define BEMAN_IV_THROW_OR_ABORT (x ) abort()
38+ #else
39+ #include < stdexcept> // for length_error
40+ #define BEMAN_IV_THROW_OR_ABORT (x ) throw x
41+ #endif
42+
3443// beman::from_range_t
3544namespace beman {
3645struct from_range_t {};
@@ -269,8 +278,9 @@ struct inplace_vector
269278 static constexpr size_type capacity () noexcept { return N; }
270279
271280 constexpr void reserve (size_type n) BEMAN_IV_FREESTANDING_DELETE({
272- if (n > N) [[unlikely]]
273- throw std::bad_alloc ();
281+ if (n > N) [[unlikely]] {
282+ BEMAN_IV_THROW_OR_ABORT (std::bad_alloc ());
283+ }
274284 });
275285
276286 constexpr void shrink_to_fit () {}
@@ -362,7 +372,7 @@ struct inplace_vector
362372 requires(std::constructible_from<T, Args...>)
363373 BEMAN_IV_FREESTANDING_DELETE({
364374 if (!try_emplace_back (std::forward<Args>(args)...)) [[unlikely]]
365- throw std::bad_alloc ();
375+ BEMAN_IV_THROW_OR_ABORT ( std::bad_alloc () );
366376 return back ();
367377 });
368378 constexpr T &push_back (const T &x)
@@ -405,16 +415,30 @@ struct inplace_vector
405415 requires(std::constructible_from<T, std::ranges::range_reference_t <R>>)
406416 BEMAN_IV_FREESTANDING_DELETE({
407417 if constexpr (std::ranges::sized_range<R>) {
408- if (size () + std::ranges::size (rg) > capacity ()) [[unlikely]]
409- throw std::bad_alloc ();
418+ if (size () + std::ranges::size (rg) > capacity ()) [[unlikely]] {
419+ BEMAN_IV_THROW_OR_ABORT (std::bad_alloc ());
420+ }
410421 }
411422 for (auto &&e : rg) {
412- if (size () == capacity ()) [[unlikely]]
413- throw std::bad_alloc ();
423+ if (size () == capacity ()) [[unlikely]] {
424+ BEMAN_IV_THROW_OR_ABORT (std::bad_alloc ());
425+ }
414426 emplace_back (std::forward<decltype (e)>(e));
415427 }
416428 });
417429
430+ template <details::inplace_vector::container_compatible_range<T> R>
431+ constexpr std::ranges::borrowed_iterator_t <R> try_append_range (R &&rg)
432+ requires(std::constructible_from<T, std::ranges::range_reference_t <R>>)
433+ {
434+ auto it = std::ranges::begin (rg);
435+ const auto end = std::ranges::end (rg);
436+ for (; size () != capacity () && it != end; ++it) {
437+ unchecked_emplace_back (*it);
438+ }
439+ return it;
440+ }
441+
418442 template <class ... Args>
419443 constexpr iterator emplace (const_iterator position, Args &&...args)
420444 requires(std::constructible_from<T, Args...> && std::movable<T>)
@@ -436,8 +460,9 @@ struct inplace_vector
436460 assert_iterator_in_range (position);
437461 if constexpr (std::random_access_iterator<InputIterator>) {
438462 if (size () + static_cast <size_type>(std::distance (first, last)) >
439- capacity ()) [[unlikely]]
440- throw std::bad_alloc{};
463+ capacity ()) [[unlikely]] {
464+ BEMAN_IV_THROW_OR_ABORT (std::bad_alloc ());
465+ }
441466 }
442467 auto b = end ();
443468 for (; first != last; ++first)
@@ -541,9 +566,9 @@ struct inplace_vector
541566 BEMAN_IV_FREESTANDING_DELETE({
542567 if (sz == size ())
543568 return ;
544- else if (sz > N) [[unlikely]]
545- throw std::bad_alloc{} ;
546- else if (sz > size ())
569+ else if (sz > N) [[unlikely]] {
570+ BEMAN_IV_THROW_OR_ABORT ( std::bad_alloc ()) ;
571+ } else if (sz > size ())
547572 insert (end (), sz - size (), c);
548573 else {
549574 unsafe_destroy (begin () + sz, end ());
@@ -555,26 +580,26 @@ struct inplace_vector
555580 BEMAN_IV_FREESTANDING_DELETE({
556581 if (sz == size ())
557582 return ;
558- else if (sz > N) [[unlikely]]
559- throw std::bad_alloc{} ;
560- else if (sz > size ())
583+ else if (sz > N) [[unlikely]] {
584+ BEMAN_IV_THROW_OR_ABORT ( std::bad_alloc ()) ;
585+ } else if (sz > size ()) {
561586 while (size () != sz)
562587 emplace_back (T{});
563- else {
588+ } else {
564589 unsafe_destroy (begin () + sz, end ());
565590 unsafe_set_size (sz);
566591 }
567592 });
568593
569594 constexpr reference at (size_type pos) BEMAN_IV_FREESTANDING_DELETE({
570595 if (pos >= size ()) [[unlikely]]
571- throw std::out_of_range (" inplace_vector::at" );
596+ BEMAN_IV_THROW_OR_ABORT ( std::out_of_range (" inplace_vector::at" ) );
572597 return details::inplace_vector::index (*this , pos);
573598 });
574599 constexpr const_reference at (size_type pos) const
575600 BEMAN_IV_FREESTANDING_DELETE({
576601 if (pos >= size ()) [[unlikely]]
577- throw std::out_of_range (" inplace_vector::at" );
602+ BEMAN_IV_THROW_OR_ABORT ( std::out_of_range (" inplace_vector::at" ) );
578603 return details::inplace_vector::index (*this , pos);
579604 });
580605
@@ -593,7 +618,7 @@ struct inplace_vector
593618 std::copyable<T>)
594619 {
595620 for (auto &&e : x)
596- emplace_back (e);
621+ unchecked_emplace_back (e);
597622 }
598623
599624 constexpr inplace_vector (inplace_vector &&x)
@@ -605,7 +630,7 @@ struct inplace_vector
605630 std::movable<T>)
606631 {
607632 for (auto &&e : x)
608- emplace_back (std::move (e));
633+ unchecked_emplace_back (std::move (e));
609634 }
610635
611636 constexpr inplace_vector &operator =(const inplace_vector &x)
@@ -623,7 +648,7 @@ struct inplace_vector
623648 {
624649 clear ();
625650 for (auto &&e : x)
626- emplace_back (e);
651+ unchecked_emplace_back (e);
627652 return *this ;
628653 }
629654
@@ -642,7 +667,16 @@ struct inplace_vector
642667 {
643668 clear ();
644669 for (auto &&e : x)
645- emplace_back (std::move (e));
670+ unchecked_emplace_back (std::move (e));
671+ return *this ;
672+ }
673+
674+ constexpr inplace_vector &operator =(std::initializer_list<T> il)
675+ requires (std::constructible_from<
676+ T, std::ranges::range_reference_t <std::initializer_list<T>>> &&
677+ std::movable<T>)
678+ {
679+ assign_range (il);
646680 return *this ;
647681 }
648682
0 commit comments