12#ifndef dealii_cxx26_inplace_vector_h
13#define dealii_cxx26_inplace_vector_h
18#ifdef DEAL_II_HAVE_CXX26
19# include <inplace_vector>
30# include <initializer_list>
32# include <type_traits>
35#include <boost/serialization/array_wrapper.hpp>
36#include <boost/serialization/collection_size_type.hpp>
37#include <boost/serialization/split_free.hpp>
43#ifndef DEAL_II_HAVE_CXX26
45 "The current operation requires more capacity than the "
46 "container can provide.");
76 template <
typename T, std::
size_t N>
116 internal_resize<true>(n);
126 throw std::bad_alloc();
134 template <
class InputIterator>
140 if constexpr (std::is_integral_v<InputIterator>)
142 static_cast<const T &
>(last));
144 internal_append<InputIterator, true, false>(
first, last);
147# ifdef DEAL_II_HAVE_CXX20
152 requires(std::is_trivially_copy_constructible_v<T>)
160 std::is_nothrow_copy_constructible_v<T>)
166# ifdef DEAL_II_HAVE_CXX20
171 requires(std::is_trivially_move_constructible_v<T>)
179 std::is_nothrow_move_constructible_v<T>)
182 internal_append<iterator, false, true>(other.begin(), other.end());
192 throw std::bad_alloc();
196# ifdef DEAL_II_HAVE_CXX20
201 requires(std::is_trivially_destructible_v<T>)
205# ifdef DEAL_II_HAVE_CXX20
225# ifdef DEAL_II_HAVE_CXX20
228 requires((std::is_trivially_copy_assignable_v<T> &&
229 std::is_trivially_copy_constructible_v<T> &&
230 std::is_trivially_destructible_v<T>))
240 if (std::addressof(other) !=
this)
246# ifdef DEAL_II_HAVE_CXX20
252 requires(std::is_trivially_move_assignable_v<T> &&
253 std::is_trivially_move_constructible_v<T> &&
254 std::is_trivially_destructible_v<T>)
263 std::is_nothrow_move_assignable_v<T>
264 &&std::is_nothrow_move_constructible_v<T>)
266 if (std::addressof(other) !=
this)
267 internal_assign<iterator, false, true>(other.begin(), other.end());
279 throw std::bad_alloc();
295 template <
class InputIterator>
299 if constexpr (std::is_integral_v<InputIterator>)
312 throw std::bad_alloc();
325 throw std::bad_alloc();
491 internal_resize<true>(n);
501 internal_resize<true>(n, value);
510 static constexpr void
514 throw std::bad_alloc();
521 static constexpr void
559 throw std::out_of_range(
"inplace_vector::at(): index " +
560 std::to_string(n) +
" out of range");
572 throw std::out_of_range(
"inplace_vector::at(): index " +
573 std::to_string(n) +
" out of range");
658 template <
class... Args>
662 internal_resize<true>(
size() + 1, std::forward<Args>(args)...);
675 internal_resize<true>(
size() + 1, value);
688 internal_resize<true>(
size() + 1, std::forward<T>(value));
700 internal_resize<true>(
size() - 1);
710 template <
class... Args>
715 internal_resize<false>(
size() + 1, std::forward<Args>(args)...);
729 internal_resize<false>(
size() + 1, value);
743 internal_resize<false>(
size() + 1, std::forward<T>(value));
751 template <
class... Args>
755 const auto index = position -
cbegin();
760 internal_resize<true>(
size() + 1, std::forward<Args>(args)...);
766 return begin() + index;
775 return emplace(position, value);
784 return emplace(position, std::move(value));
802 template <
typename InputIterator>
806 if constexpr (std::is_integral_v<InputIterator>)
810 static_cast<const T &
>(last));
814 const auto original_size =
size();
816 const auto index = position -
cbegin();
819 const auto n_new_elements =
820 internal_append<InputIterator>(
first, last);
822 std::rotate(
begin() + index,
begin() + original_size,
end());
823 return begin() + index;
833 return insert(position, init.begin(), init.end());
842 const auto index = position -
cbegin();
848 return begin() + index;
857 const auto original_size =
size();
858 const auto distance = std::distance(
first, last);
860 const auto last_index = last -
cbegin();
861 Assert(first_index <= last_index,
863 std::rotate(
begin() + first_index,
begin() + last_index,
end());
864 internal_resize<true>(
size() - distance);
867 return begin() + first_index;
875 std::is_nothrow_swappable_v<T> &&std::is_nothrow_move_constructible_v<T>)
877 if (std::addressof(other) ==
this)
880 auto &smaller =
size() < other.size() ? *this : other;
881 const auto smaller_size = smaller.size();
882 auto &larger =
size() < other.size() ? other : *
this;
886 for (std::size_t i = smaller.size(); i < larger.size(); ++i)
888 if constexpr (std::is_nothrow_move_constructible_v<T>)
889 smaller.push_back(std::move(larger[i]));
891 smaller.push_back(larger[i]);
893 larger.resize(smaller_size);
895 for (std::size_t i = 0; i < smaller_size; ++i)
896 swap(smaller[i], larger[i]);
904 std::is_nothrow_swappable_v<T> &&std::is_nothrow_move_constructible_v<T>)
958 return !(*
this == other);
977 template <
bool check =
false,
typename... Args>
982 static_assert(std::is_constructible_v<T, Args...>);
985 throw std::bad_alloc();
1000 new (
end()) T(std::forward<Args>(args)...);
1009 template <
typename InputIterator,
bool check = false,
bool move = false>
1012 !check && (move ? std::is_nothrow_move_assignable_v<T> :
1013 std::is_nothrow_copy_assignable_v<T>))
1015 static_assert(std::is_convertible_v<
decltype(*first), T>);
1029 internal_append<InputIterator, check, move>(
first, last);
1036 template <
typename InputIterator,
bool check = false,
bool move = false>
1039 !check && (move ? std::is_nothrow_move_constructible_v<T> :
1040 std::is_nothrow_copy_constructible_v<T>))
1042 static_assert(std::is_convertible_v<
decltype(*first), T>);
1049 while (
first != last)
1052 if constexpr (check)
1054 throw std::bad_alloc();
1076 std::conditional_t<N <= std::numeric_limits<std::uint8_t>::max(),
1080 N <= std::numeric_limits<buffer_size_type>::max(),
1081 "This class only supports objects of size <= the maximum size of a "
1082 "std::uint16_t (65535).");
1099 template <
typename T, std::
size_t N>
1103 return (a.
size() == b.size()) && std::equal(a.
begin(), a.
end(), b.begin());
1111 template <
typename T, std::
size_t N>
1123 template <
typename T, std::
size_t N>
1127 return std::lexicographical_compare(a.
begin(), a.
end(), b.begin(), b.end());
1135 template <
typename T, std::
size_t N>
1147 template <
typename T, std::
size_t N>
1159 template <
typename T, std::
size_t N>
1172 template <
typename T, std::
size_t N,
typename U = T>
1176 auto it = std::remove(vec.
begin(), vec.
end(), value);
1177 const auto count = std::distance(it, vec.
end());
1188 template <
typename T, std::
size_t N,
typename Predicate>
1192 auto it = std::remove_if(vec.
begin(), vec.
end(), pred);
1193 const auto count = std::distance(it, vec.
end());
1200 using std::erase_if;
1201 using std::inplace_vector;
1209 namespace serialization
1216 template <
class Archive,
typename T, std::
size_t N>
1220 const unsigned int file_version)
1222 boost::serialization::split_free(ar, t, file_version);
1230 template <
class Archive,
typename T, std::
size_t N>
1233 const ::std_cxx26::inplace_vector<T, N> &vec,
1234 const unsigned int )
1236 const boost::serialization::collection_size_type count(vec.size());
1239 ar << boost::serialization::make_array(vec.data(), count);
1242 template <
class Archive,
typename T, std::
size_t N>
1246 const unsigned int )
1248 boost::serialization::collection_size_type count(vec.
size());
1252 ar >> boost::serialization::make_array(vec.
data(), count);
constexpr inplace_vector() noexcept
inplace_vector(InputIterator first, InputIterator last)
iterator insert(const_iterator position, const T &value)
inplace_vector & operator=(std::initializer_list< T > init)
const_reference back() const
bool operator>(const inplace_vector< T, N > &a, const inplace_vector< T, N > &b)
constexpr iterator end() noexcept
constexpr reverse_iterator rbegin() noexcept
constexpr const_reverse_iterator crbegin() const noexcept
constexpr void internal_resize(const size_type n, Args &&...args) noexcept(!check)
const_reference front() const
iterator erase(const_iterator position)
constexpr size_type size() const noexcept
reference push_back(const T &value)
reference at(size_type n)
void assign(InputIterator first, InputIterator last)
std::size_t erase_if(std_cxx26::inplace_vector< T, N > &vec, Predicate pred)
void assign(std::initializer_list< T > init)
constexpr const_reverse_iterator crend() const noexcept
constexpr iterator begin() noexcept
std::reverse_iterator< const_iterator > const_reverse_iterator
reference emplace_back(Args &&...args)
constexpr inplace_vector(std::initializer_list< T > init)
iterator emplace(const_iterator position, Args &&...args)
void resize(size_type n, const T &value)
void swap(inplace_vector &other) noexcept(std::is_nothrow_swappable_v< T > &&std::is_nothrow_move_constructible_v< T >)
const_reference at(size_type n) const
constexpr const_iterator begin() const noexcept
iterator erase(const_iterator first, const_iterator last)
bool operator>=(const inplace_vector< T, N > &a, const inplace_vector< T, N > &b)
constexpr reverse_iterator rend() noexcept
reference unchecked_push_back(const T &value)
constexpr bool empty() const noexcept
bool operator!=(const inplace_vector< T, N > &a, const inplace_vector< T, N > &b)
friend void swap(inplace_vector &x, inplace_vector &y) noexcept(std::is_nothrow_swappable_v< T > &&std::is_nothrow_move_constructible_v< T >)
iterator insert(const_iterator position, InputIterator first, InputIterator last)
inplace_vector(const inplace_vector &other) noexcept(std::is_nothrow_copy_constructible_v< T >)
static constexpr size_type max_size() noexcept
void internal_assign(InputIterator first, InputIterator last) noexcept(!check &&(move ? std::is_nothrow_move_assignable_v< T > :std::is_nothrow_copy_assignable_v< T >))
std::reverse_iterator< iterator > reverse_iterator
static constexpr void reserve(size_type n)
inplace_vector(size_type n)
inplace_vector & operator=(const inplace_vector &other)
const_pointer const_iterator
const value_type & const_reference
const value_type * const_pointer
constexpr const_iterator cend() const noexcept
reference push_back(T &&value)
std::size_t erase(std_cxx26::inplace_vector< T, N > &vec, const U &value)
reference operator[](size_type n)
static constexpr void shrink_to_fit() noexcept
const T * data() const noexcept
const_reference operator[](size_type n) const
bool operator==(const inplace_vector< T, N > &a, const inplace_vector< T, N > &b)
inplace_vector(size_type n, const T &value)
std::ptrdiff_t difference_type
constexpr const_iterator cbegin() const noexcept
iterator insert(const_iterator position, size_type n, const T &value)
iterator insert(const_iterator position, T &&value)
iterator insert(const_iterator position, std::initializer_list< T > init)
constexpr const_iterator end() const noexcept
reference unchecked_push_back(T &&value)
reference unchecked_emplace_back(Args &&...args)
std::conditional_t< N<=std::numeric_limits< std::uint8_t >::max(), std::uint8_t, std::uint16_t > buffer_size_type
constexpr size_type internal_append(InputIterator first, InputIterator last) noexcept(!check &&(move ? std::is_nothrow_move_constructible_v< T > :std::is_nothrow_copy_constructible_v< T >))
void assign(size_type n, const T &value)
constexpr const_reverse_iterator rend() const noexcept
constexpr const_reverse_iterator rbegin() const noexcept
inplace_vector(inplace_vector &&other) noexcept(std::is_nothrow_move_constructible_v< T >)
static constexpr size_type capacity() noexcept
buffer_size_type n_elements
constexpr void clear() noexcept
inplace_vector & operator=(inplace_vector &&other) noexcept(std::is_nothrow_move_assignable_v< T > &&std::is_nothrow_move_constructible_v< T >)
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
static ::ExceptionBase & ExcCapacityExceeded()
static ::ExceptionBase & ExcEmptyObject()
#define Assert(cond, exc)
#define AssertIndexRange(index, range)
#define DeclExceptionMsg(Exception, defaulttext)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcMessage(std::string arg1)
void load(Archive &ar, ::std_cxx26::inplace_vector< T, N > &vec, const unsigned int)
void save(Archive &ar, const ::std_cxx26::inplace_vector< T, N > &vec, const unsigned int)
void serialize(Archive &ar, ::std_cxx26::inplace_vector< T, N > &t, const unsigned int file_version)
bool operator<(const SynchronousIterators< Iterators > &a, const SynchronousIterators< Iterators > &b)