diff --git a/include/rexy/list.hpp b/include/rexy/list.hpp index e26cd49..1c12067 100644 --- a/include/rexy/list.hpp +++ b/include/rexy/list.hpp @@ -20,12 +20,14 @@ #define REXY_LLIST_HPP #include //size_t, ptrdiff_t -#include "allocator.hpp" //TODO +#include "allocator.hpp" #include "detail/hasallocator.hpp" +#include "traits.hpp" #include //bidirectional_iterator_tag, reverse_iterator #include //allocator_traits #include #include //pair +#include namespace rexy{ @@ -74,21 +76,58 @@ namespace rexy{ size_type m_size = 0; public: - constexpr list(void) = default; - constexpr explicit list(const allocator_type& alloc); - REXY_CPP20_CONSTEXPR list(size_type count, const_reference value = value_type(), const allocator_type& = allocator_type()); - REXY_CPP20_CONSTEXPR explicit list(size_type count, const allocator_type& alloc = allocator_type()); + constexpr list(void)noexcept = default; + + constexpr explicit list(const allocator_type& alloc)noexcept; + + REXY_CPP20_CONSTEXPR + list(size_type count, const_reference value = value_type(), const allocator_type& = allocator_type())noexcept( + std::is_nothrow_copy_constructible_v && + is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + explicit list(size_type count, const allocator_type& alloc = allocator_type())noexcept( + std::is_nothrow_default_constructible_v && + is_nothrow_allocator_v); + template - REXY_CPP20_CONSTEXPR list(InputIt first, InputIt last, const allocator_type& alloc = allocator_type()); - REXY_CPP20_CONSTEXPR list(const list& other, const allocator_type& alloc = allocator_type()); - REXY_CPP20_CONSTEXPR list(list&& other, const allocator_type& alloc = allocator_type()); - REXY_CPP20_CONSTEXPR list(std::initializer_list l, const allocator_type& alloc = allocator_type()); + REXY_CPP20_CONSTEXPR + list(InputIt first, InputIt last, const allocator_type& alloc = allocator_type())noexcept( + std::is_nothrow_constructible_v && + is_nothrow_allocator_v); - REXY_CPP20_CONSTEXPR ~list(void); + REXY_CPP20_CONSTEXPR + list(const list& other, const allocator_type& alloc = allocator_type())noexcept( + std::is_nothrow_copy_constructible_v && + is_nothrow_allocator_v); - REXY_CPP20_CONSTEXPR list& operator=(const list& other); - REXY_CPP20_CONSTEXPR list& operator=(list&& other); - REXY_CPP20_CONSTEXPR list& operator=(std::initializer_list l); + REXY_CPP20_CONSTEXPR + list(list&& other, const allocator_type& alloc = allocator_type())noexcept; + + REXY_CPP20_CONSTEXPR + list(std::initializer_list l, const allocator_type& alloc = allocator_type())noexcept( + std::is_nothrow_constructible_v && + is_nothrow_allocator_v); + + + REXY_CPP20_CONSTEXPR + ~list(void)noexcept( + std::is_nothrow_destructible_v && + is_nothrow_allocator_v); + + + REXY_CPP20_CONSTEXPR + list& operator=(const list& other)noexcept( + std::is_nothrow_copy_constructible_v && + is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + list& operator=(list&& other)noexcept; + + REXY_CPP20_CONSTEXPR + list& operator=(std::initializer_list l)noexcept( + std::is_nothrow_constructible_v && + is_nothrow_allocator_v); constexpr bool operator==(const list& other)const noexcept; #if __cpp_impl_three_way_comparison @@ -101,17 +140,45 @@ namespace rexy{ constexpr bool operator>=(const list& other)const noexcept; #endif - REXY_CPP20_CONSTEXPR void assign(size_type count, const_reference value); + + REXY_CPP20_CONSTEXPR + void assign(size_type count, const_reference value)noexcept( + std::conditional_t< + std::is_copy_assignable_v, + std::is_nothrow_copy_assignable, + std::true_type>::value && + std::is_nothrow_copy_constructible_v && + std::is_nothrow_destructible_v && + is_nothrow_allocator_v); + template - REXY_CPP20_CONSTEXPR void assign(InputIt first, InputIt last); - REXY_CPP20_CONSTEXPR void assign(std::initializer_list l); + REXY_CPP20_CONSTEXPR + void assign(InputIt first, InputIt last)noexcept( + std::conditional_t< + std::is_assignable_v, + std::is_nothrow_assignable, + std::true_type>::value && + std::is_nothrow_constructible_v && + std::is_nothrow_destructible_v && + is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + void assign(std::initializer_list l)noexcept( + std::conditional_t< + std::is_assignable_v, + std::is_nothrow_assignable, + std::true_type>::value && + std::is_nothrow_constructible_v && + std::is_nothrow_destructible_v && + is_nothrow_allocator_v); + constexpr allocator_type get_allocator(void)const noexcept; - constexpr reference front(void); - constexpr const_reference front(void)const; - constexpr reference back(void); - constexpr const_reference back(void)const; + constexpr reference front(void)noexcept; + constexpr const_reference front(void)const noexcept; + constexpr reference back(void)noexcept; + constexpr const_reference back(void)const noexcept; constexpr iterator begin(void)noexcept; constexpr const_iterator begin(void)const noexcept; @@ -137,74 +204,193 @@ namespace rexy{ constexpr size_type size(void)const noexcept; constexpr size_type max_size(void)const noexcept; - REXY_CPP20_CONSTEXPR void clear(void)noexcept; - REXY_CPP20_CONSTEXPR iterator insert(const_iterator pos, const_reference value); - REXY_CPP20_CONSTEXPR iterator insert(const_iterator pos, value_type&& value); - REXY_CPP20_CONSTEXPR iterator insert(const_iterator pos, size_type count, const_reference value); + REXY_CPP20_CONSTEXPR + void clear(void)noexcept( + std::is_nothrow_destructible_v && + is_nothrow_allocator_v); + + + REXY_CPP20_CONSTEXPR + iterator insert(const_iterator pos, const_reference value)noexcept( + std::is_nothrow_copy_constructible_v && + is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + iterator insert(const_iterator pos, value_type&& value)noexcept( + std::is_nothrow_move_constructible_v && + is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + iterator insert(const_iterator pos, size_type count, const_reference value)noexcept( + std::is_nothrow_copy_constructible_v && + is_nothrow_allocator_v); + template - REXY_CPP20_CONSTEXPR iterator insert(const_iterator pos, InputIt first, InputIt last); - REXY_CPP20_CONSTEXPR iterator insert(const_iterator pos, std::initializer_list l); + REXY_CPP20_CONSTEXPR + iterator insert(const_iterator pos, InputIt first, InputIt last)noexcept( + std::is_nothrow_constructible_v && + is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + iterator insert(const_iterator pos, std::initializer_list l)noexcept( + std::is_nothrow_constructible_v && + is_nothrow_allocator_v); template - REXY_CPP20_CONSTEXPR iterator emplace(const_iterator pos, Args&&... args); + REXY_CPP20_CONSTEXPR + iterator emplace(const_iterator pos, Args&&... args)noexcept( + std::is_nothrow_constructible_v && + is_nothrow_allocator_v); - REXY_CPP20_CONSTEXPR iterator erase(const_iterator pos); - REXY_CPP20_CONSTEXPR iterator erase(const_iterator first, const_iterator last); - REXY_CPP20_CONSTEXPR reference push_back(const_reference value); - REXY_CPP20_CONSTEXPR reference push_back(value_type&& value); + REXY_CPP20_CONSTEXPR + iterator erase(const_iterator pos)noexcept( + std::is_nothrow_destructible_v && + is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + iterator erase(const_iterator first, const_iterator last)noexcept( + std::is_nothrow_destructible_v && + is_nothrow_allocator_v); + + + REXY_CPP20_CONSTEXPR + reference push_back(const_reference value)noexcept( + std::is_nothrow_copy_constructible_v && + is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + reference push_back(value_type&& value)noexcept( + std::is_nothrow_move_constructible_v && + is_nothrow_allocator_v); + template - REXY_CPP20_CONSTEXPR reference emplace_back(Args&&... args); + REXY_CPP20_CONSTEXPR + reference emplace_back(Args&&... args)noexcept( + std::is_nothrow_constructible_v && + is_nothrow_allocator_v); - REXY_CPP20_CONSTEXPR void pop_back(void); + REXY_CPP20_CONSTEXPR + void pop_back(void)noexcept( + std::is_nothrow_destructible_v && + is_nothrow_allocator_v); + + + REXY_CPP20_CONSTEXPR + reference push_front(const_reference value)noexcept( + std::is_nothrow_copy_constructible_v && + is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + reference push_front(value_type&& value)noexcept( + std::is_nothrow_move_constructible_v && + is_nothrow_allocator_v); - REXY_CPP20_CONSTEXPR reference push_front(const_reference value); - REXY_CPP20_CONSTEXPR reference push_front(value_type&& value); template - REXY_CPP20_CONSTEXPR reference emplace_front(Args&&... args); + REXY_CPP20_CONSTEXPR + reference emplace_front(Args&&... args)noexcept( + std::is_nothrow_constructible_v && + is_nothrow_allocator_v); - REXY_CPP20_CONSTEXPR void pop_front(void); + REXY_CPP20_CONSTEXPR + void pop_front(void)noexcept( + std::is_nothrow_destructible_v && + is_nothrow_allocator_v); - REXY_CPP20_CONSTEXPR void resize(size_type count); - REXY_CPP20_CONSTEXPR void resize(size_type count, value_type value); - REXY_CPP20_CONSTEXPR void swap(list& other); + REXY_CPP20_CONSTEXPR + void resize(size_type count)noexcept( + std::is_nothrow_default_constructible_v && + std::is_nothrow_destructible_v && + is_nothrow_allocator_v); - REXY_CPP20_CONSTEXPR void merge(list&& other); + REXY_CPP20_CONSTEXPR + void resize(size_type count, value_type value)noexcept( + std::is_nothrow_copy_constructible_v && + std::is_nothrow_destructible_v && + is_nothrow_allocator_v); + + + REXY_CPP20_CONSTEXPR + void swap(list& other)noexcept; + + + REXY_CPP20_CONSTEXPR + void merge(list&& other)noexcept; template - REXY_CPP20_CONSTEXPR void merge(list&& other, Comp comp); + REXY_CPP20_CONSTEXPR + void merge(list&& other, Comp comp)noexcept; - REXY_CPP20_CONSTEXPR void splice(const_iterator pos, list&& other); - REXY_CPP20_CONSTEXPR void splice(const_iterator pos, list&& other, const_iterator it); - REXY_CPP20_CONSTEXPR void splice(const_iterator pos, list&& other, const_iterator first, const_iterator last); - REXY_CPP20_CONSTEXPR size_type remove(const_reference value); + REXY_CPP20_CONSTEXPR + void splice(const_iterator pos, list&& other)noexcept; + + REXY_CPP20_CONSTEXPR + void splice(const_iterator pos, list&& other, const_iterator it)noexcept; + + REXY_CPP20_CONSTEXPR + void splice(const_iterator pos, list&& other, const_iterator first, const_iterator last)noexcept; + + + REXY_CPP20_CONSTEXPR + size_type remove(const_reference value)noexcept( + std::is_nothrow_destructible_v && + is_nothrow_allocator_v); + template - REXY_CPP20_CONSTEXPR size_type remove_if(UnaryPred p); + REXY_CPP20_CONSTEXPR + size_type remove_if(UnaryPred p)noexcept( + std::is_nothrow_destructible_v && + is_nothrow_allocator_v); - REXY_CPP20_CONSTEXPR void reverse(void)noexcept; + REXY_CPP20_CONSTEXPR + void reverse(void)noexcept; + + REXY_CPP20_CONSTEXPR + size_type unique(void)noexcept( + std::is_nothrow_destructible_v && + is_nothrow_allocator_v); - REXY_CPP20_CONSTEXPR size_type unique(void); template - REXY_CPP20_CONSTEXPR size_type unique(BinaryPred p); + REXY_CPP20_CONSTEXPR + size_type unique(BinaryPred p)noexcept( + std::is_nothrow_destructible_v && + is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + void sort(void)noexcept; - REXY_CPP20_CONSTEXPR void sort(void); template - REXY_CPP20_CONSTEXPR void sort(Comp comp); + REXY_CPP20_CONSTEXPR + void sort(Comp comp)noexcept; + + private: + template - REXY_CPP20_CONSTEXPR void iterator_initialize_(InputIt first, InputIt last); - REXY_CPP20_CONSTEXPR void constant_initialize_(size_type count, const_reference value); - REXY_CPP20_CONSTEXPR void default_initialize_(size_type count); + REXY_CPP20_CONSTEXPR + void iterator_initialize_(InputIt first, InputIt last)noexcept( + std::is_nothrow_constructible_v && + is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + void constant_initialize_(size_type count, const_reference value)noexcept( + std::is_nothrow_copy_constructible_v && + is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + void default_initialize_(size_type count)noexcept( + std::is_nothrow_default_constructible_v && + is_nothrow_allocator_v); template - static iterator mergesort(iterator first, size_type firstlen, Comp comp); - static std::pair ms_split(iterator it, size_type len); + static iterator mergesort(iterator first, size_type firstlen, Comp comp)noexcept; + static std::pair ms_split(iterator it, size_type len)noexcept; - static void insert_node_(detail::list_node_base* prev, detail::list_node_base* n); - static void remove_node_(detail::list_node_base* rm); - static detail::list_node_base* get_next_then_move_node_(detail::list_node_base* dest, detail::list_node_base* n); + static void insert_node_(detail::list_node_base* prev, detail::list_node_base* n)noexcept; + static void remove_node_(detail::list_node_base* rm)noexcept; + static detail::list_node_base* get_next_then_move_node_(detail::list_node_base* dest, detail::list_node_base* n)noexcept; }; } diff --git a/include/rexy/list.tpp b/include/rexy/list.tpp index 26405d5..68a2cb2 100644 --- a/include/rexy/list.tpp +++ b/include/rexy/list.tpp @@ -173,62 +173,91 @@ namespace rexy{ } template - constexpr list::list(const allocator_type& alloc): + constexpr list::list(const allocator_type& alloc)noexcept: node_allocator_type(alloc){} template - REXY_CPP20_CONSTEXPR list::list(size_type count, const_reference value, const allocator_type& alloc): + REXY_CPP20_CONSTEXPR + list::list(size_type count, const_reference value, const allocator_type& alloc)noexcept( + std::is_nothrow_copy_constructible_v && + is_nothrow_allocator_v): node_allocator_type(alloc) { constant_initialize_(count, value); } template - REXY_CPP20_CONSTEXPR list::list(size_type count, const allocator_type& alloc): + REXY_CPP20_CONSTEXPR + list::list(size_type count, const allocator_type& alloc)noexcept( + std::is_nothrow_default_constructible_v && + is_nothrow_allocator_v): node_allocator_type(alloc) { default_initialize_(count); } template template - REXY_CPP20_CONSTEXPR list::list(InputIt first, InputIt last, const allocator_type& alloc): + REXY_CPP20_CONSTEXPR + list::list(InputIt first, InputIt last, const allocator_type& alloc)noexcept( + std::is_nothrow_constructible_v && + is_nothrow_allocator_v): node_allocator_type(alloc) { iterator_initialize_(first, last); } template - REXY_CPP20_CONSTEXPR list::list(const list& other, const allocator_type& alloc): + REXY_CPP20_CONSTEXPR + list::list(const list& other, const allocator_type& alloc)noexcept( + std::is_nothrow_copy_constructible_v && + is_nothrow_allocator_v): node_allocator_type(alloc) { iterator_initialize_(other.begin(), other.end()); } template - REXY_CPP20_CONSTEXPR list::list(list&& other, const allocator_type& alloc): + REXY_CPP20_CONSTEXPR + list::list(list&& other, const allocator_type& alloc)noexcept: node_allocator_type(alloc) { swap(other); } template - REXY_CPP20_CONSTEXPR list::list(std::initializer_list l, const allocator_type& alloc): + REXY_CPP20_CONSTEXPR + list::list(std::initializer_list l, const allocator_type& alloc)noexcept( + std::is_nothrow_constructible_v && + is_nothrow_allocator_v): node_allocator_type(alloc) { iterator_initialize_(l.begin(), l.end()); } template - REXY_CPP20_CONSTEXPR list::~list(void){ + REXY_CPP20_CONSTEXPR + list::~list(void)noexcept( + std::is_nothrow_destructible_v && + is_nothrow_allocator_v) + { clear(); } template - REXY_CPP20_CONSTEXPR auto list::operator=(const list& other) -> list&{ + REXY_CPP20_CONSTEXPR + auto list::operator=(const list& other)noexcept( + std::is_nothrow_copy_constructible_v && + is_nothrow_allocator_v) -> list& + { return (*this = list(other)); } template - REXY_CPP20_CONSTEXPR auto list::operator=(list&& other) -> list&{ + REXY_CPP20_CONSTEXPR + auto list::operator=(list&& other)noexcept -> list&{ swap(other); return *this; } template - REXY_CPP20_CONSTEXPR auto list::operator=(std::initializer_list l) -> list&{ + REXY_CPP20_CONSTEXPR + auto list::operator=(std::initializer_list l)noexcept( + std::is_nothrow_constructible_v && + is_nothrow_allocator_v) -> list& + { return (*this = list(l)); } @@ -267,36 +296,37 @@ namespace rexy{ #endif template - REXY_CPP20_CONSTEXPR void list::assign(size_type count, const_reference value){ + REXY_CPP20_CONSTEXPR + void list::assign(size_type count, const_reference value)noexcept( + std::conditional_t< + std::is_copy_assignable_v, + std::is_nothrow_copy_assignable, + std::true_type>::value && + std::is_nothrow_copy_constructible_v && + std::is_nothrow_destructible_v && + is_nothrow_allocator_v) + { assign(sized_constant_iterator{value, count}, sized_constant_iterator{{}, 0}); } template template - REXY_CPP20_CONSTEXPR void list::iterator_initialize_(InputIt first, InputIt last){ - for(;first != last;++first){ - emplace_back(*first); - } - } - template - REXY_CPP20_CONSTEXPR void list::constant_initialize_(size_type count, const_reference value){ - for(;count > 0;--count){ - emplace_back(value); - } - } - template - REXY_CPP20_CONSTEXPR void list::default_initialize_(size_type count){ - for(;count > 0;--count){ - emplace_back(); - } - } - template - template - REXY_CPP20_CONSTEXPR void list::assign(InputIt first, InputIt last){ + REXY_CPP20_CONSTEXPR + void list::assign(InputIt first, InputIt last)noexcept( + std::conditional_t< + std::is_assignable_v, + std::is_nothrow_assignable, + std::true_type>::value && + std::is_nothrow_constructible_v && + std::is_nothrow_destructible_v && + is_nothrow_allocator_v) + { auto current = begin(); size_type i = 0; - for(;i < m_size && first != last;++i){ - *current++ = *first++; + if constexpr(std::is_assignable_v){ + for(;i < m_size && first != last;++i){ + *current++ = *first++; + } } if(first != last){ m_size = i; @@ -308,7 +338,16 @@ namespace rexy{ } } template - REXY_CPP20_CONSTEXPR void list::assign(std::initializer_list l){ + REXY_CPP20_CONSTEXPR + void list::assign(std::initializer_list l)noexcept( + std::conditional_t< + std::is_assignable_v, + std::is_nothrow_assignable, + std::true_type>::value && + std::is_nothrow_constructible_v && + std::is_nothrow_destructible_v && + is_nothrow_allocator_v) + { assign(l.begin(), l.end()); } @@ -317,13 +356,13 @@ namespace rexy{ //Direct accessors template - constexpr auto list::front(void) -> reference{return *begin();} + constexpr auto list::front(void)noexcept -> reference{return *begin();} template - constexpr auto list::front(void)const -> const_reference{return *begin();} + constexpr auto list::front(void)const noexcept -> const_reference{return *begin();} template - constexpr auto list::back(void) -> reference{return *(--end());} + constexpr auto list::back(void)noexcept -> reference{return *(--end());} template - constexpr auto list::back(void)const -> const_reference{return *(--end());} + constexpr auto list::back(void)const noexcept-> const_reference{return *(--end());} //Iterators template @@ -339,9 +378,7 @@ namespace rexy{ template constexpr auto list::cend(void)const noexcept -> const_iterator{return const_iterator{&m_sentinel};} template - constexpr auto list::next(iterator i)noexcept -> iterator{ - return i.next(); - } + constexpr auto list::next(iterator i)noexcept -> iterator{return i.next();} template constexpr auto list::next(const_iterator i)noexcept -> const_iterator{return i.next();} template @@ -370,16 +407,28 @@ namespace rexy{ constexpr auto list::max_size(void)const noexcept -> size_type{return std::numeric_limits::max();} template - REXY_CPP20_CONSTEXPR void list::clear(void)noexcept{ + REXY_CPP20_CONSTEXPR + void list::clear(void)noexcept( + std::is_nothrow_destructible_v && + is_nothrow_allocator_v) + { erase(begin(), end()); } template - REXY_CPP20_CONSTEXPR auto list::insert(const_iterator pos, const_reference value) -> iterator{ + REXY_CPP20_CONSTEXPR + auto list::insert(const_iterator pos, const_reference value)noexcept( + std::is_nothrow_copy_constructible_v && + is_nothrow_allocator_v) -> iterator + { return insert(pos, value_type{value}); } template - REXY_CPP20_CONSTEXPR auto list::insert(const_iterator pos, value_type&& value) -> iterator{ + REXY_CPP20_CONSTEXPR + auto list::insert(const_iterator pos, value_type&& value)noexcept( + std::is_nothrow_move_constructible_v && + is_nothrow_allocator_v) -> iterator + { auto* prev = (--pos).unconst().nod(); auto* next = prev->next; prev->next = this->allocate(1); @@ -389,7 +438,11 @@ namespace rexy{ return iterator{prev->next}; } template - REXY_CPP20_CONSTEXPR auto list::insert(const_iterator pos, size_type count, const_reference value) -> iterator{ + REXY_CPP20_CONSTEXPR + auto list::insert(const_iterator pos, size_type count, const_reference value)noexcept( + std::is_nothrow_copy_constructible_v && + is_nothrow_allocator_v) -> iterator + { auto start = pos.unconst(); for(auto i = count;i > 0;--i){ pos = ++(insert(pos, value_type{value})); @@ -398,7 +451,11 @@ namespace rexy{ } template template - REXY_CPP20_CONSTEXPR auto list::insert(const_iterator pos, InputIt first, InputIt last) -> iterator{ + REXY_CPP20_CONSTEXPR + auto list::insert(const_iterator pos, InputIt first, InputIt last)noexcept( + std::is_nothrow_constructible_v && + is_nothrow_allocator_v) -> iterator + { auto start = pos.unconst(); while(first != last){ pos = ++(insert(pos, *first++)); @@ -406,13 +463,21 @@ namespace rexy{ return start; } template - REXY_CPP20_CONSTEXPR auto list::insert(const_iterator pos, std::initializer_list l) -> iterator{ + REXY_CPP20_CONSTEXPR + auto list::insert(const_iterator pos, std::initializer_list l)noexcept( + std::is_nothrow_constructible_v && + is_nothrow_allocator_v) -> iterator + { return insert(pos, l.begin(), l.end()); } template template - REXY_CPP20_CONSTEXPR auto list::emplace(const_iterator pos, Args&&... args) -> iterator{ + REXY_CPP20_CONSTEXPR + auto list::emplace(const_iterator pos, Args&&... args)noexcept( + std::is_nothrow_constructible_v && + is_nothrow_allocator_v) -> iterator + { auto* prev = (--pos).unconst().nod(); auto* next = prev->next; prev->next = this->allocate(1); @@ -423,7 +488,11 @@ namespace rexy{ } template - REXY_CPP20_CONSTEXPR auto list::erase(const_iterator pos) -> iterator{ + REXY_CPP20_CONSTEXPR + auto list::erase(const_iterator pos)noexcept( + std::is_nothrow_destructible_v && + is_nothrow_allocator_v) -> iterator + { auto* n = pos.unconst().nod(); auto* next = n->next; @@ -434,7 +503,11 @@ namespace rexy{ return iterator{next}; } template - REXY_CPP20_CONSTEXPR auto list::erase(const_iterator first, const_iterator last) -> iterator{ + REXY_CPP20_CONSTEXPR + auto list::erase(const_iterator first, const_iterator last)noexcept( + std::is_nothrow_destructible_v && + is_nothrow_allocator_v) -> iterator + { while(first != last){ first = erase(first); } @@ -442,49 +515,91 @@ namespace rexy{ } template - REXY_CPP20_CONSTEXPR auto list::push_back(const_reference value) -> reference{ + REXY_CPP20_CONSTEXPR + auto list::push_back(const_reference value)noexcept( + std::is_nothrow_copy_constructible_v && + is_nothrow_allocator_v) -> reference + { return *insert(cend(), value); } template - REXY_CPP20_CONSTEXPR auto list::push_back(value_type&& value) -> reference{ + REXY_CPP20_CONSTEXPR + auto list::push_back(value_type&& value)noexcept( + std::is_nothrow_move_constructible_v && + is_nothrow_allocator_v) -> reference + { return *insert(cend(), std::move(value)); } template template - REXY_CPP20_CONSTEXPR auto list::emplace_back(Args&&... args) -> reference{ + REXY_CPP20_CONSTEXPR + auto list::emplace_back(Args&&... args)noexcept( + std::is_nothrow_constructible_v && + is_nothrow_allocator_v) -> reference + { return *emplace(cend(), std::forward(args)...); } template - REXY_CPP20_CONSTEXPR void list::pop_back(void){ + REXY_CPP20_CONSTEXPR + void list::pop_back(void)noexcept( + std::is_nothrow_destructible_v && + is_nothrow_allocator_v) + { erase(--cend()); } template - REXY_CPP20_CONSTEXPR auto list::push_front(const_reference value) -> reference{ + REXY_CPP20_CONSTEXPR + auto list::push_front(const_reference value)noexcept( + std::is_nothrow_copy_constructible_v && + is_nothrow_allocator_v) -> reference + { return insert(cbegin(), value); } template - REXY_CPP20_CONSTEXPR auto list::push_front(value_type&& value) -> reference{ + REXY_CPP20_CONSTEXPR + auto list::push_front(value_type&& value)noexcept( + std::is_nothrow_move_constructible_v && + is_nothrow_allocator_v) -> reference + { return insert(cbegin(), std::move(value)); } template template - REXY_CPP20_CONSTEXPR auto list::emplace_front(Args&&... args) -> reference{ + REXY_CPP20_CONSTEXPR + auto list::emplace_front(Args&&... args)noexcept( + std::is_nothrow_constructible_v && + is_nothrow_allocator_v) -> reference + { return emplace(cbegin(), std::forward(args)...); } template - REXY_CPP20_CONSTEXPR void list::pop_front(void){ + REXY_CPP20_CONSTEXPR + void list::pop_front(void)noexcept( + std::is_nothrow_destructible_v && + is_nothrow_allocator_v) + { erase(cbegin()); } template - REXY_CPP20_CONSTEXPR void list::resize(size_type count){ + REXY_CPP20_CONSTEXPR + void list::resize(size_type count)noexcept( + std::is_nothrow_default_constructible_v && + std::is_nothrow_destructible_v && + is_nothrow_allocator_v) + { resize(count, value_type{}); } template - REXY_CPP20_CONSTEXPR void list::resize(size_type count, value_type value){ + REXY_CPP20_CONSTEXPR + void list::resize(size_type count, value_type value)noexcept( + std::is_nothrow_copy_constructible_v && + std::is_nothrow_destructible_v && + is_nothrow_allocator_v) + { while(count > m_size){ insert(cend(), value); } @@ -494,18 +609,21 @@ namespace rexy{ } template - REXY_CPP20_CONSTEXPR void list::swap(list& other){ + REXY_CPP20_CONSTEXPR + void list::swap(list& other)noexcept{ std::swap(m_sentinel, other.m_sentinel); std::swap(m_size, other.m_size); } template - REXY_CPP20_CONSTEXPR void list::merge(list&& other){ + REXY_CPP20_CONSTEXPR + void list::merge(list&& other)noexcept{ merge(std::move(other), [](const_reference a, const_reference b){return a < b;}); } template template - REXY_CPP20_CONSTEXPR void list::merge(list&& other, Comp comp){ + REXY_CPP20_CONSTEXPR + void list::merge(list&& other, Comp comp)noexcept{ if(&other == this){ return; } @@ -524,11 +642,13 @@ namespace rexy{ } template - REXY_CPP20_CONSTEXPR void list::splice(const_iterator pos, list&& other){ + REXY_CPP20_CONSTEXPR + void list::splice(const_iterator pos, list&& other)noexcept{ splice(pos, std::move(other), other.begin(), other.end()); } template - REXY_CPP20_CONSTEXPR void list::splice(const_iterator pos, list&& other, const_iterator it){ + REXY_CPP20_CONSTEXPR + void list::splice(const_iterator pos, list&& other, const_iterator it)noexcept{ auto oit = it.unconst(); auto prev = (--pos).unconst(); remove_node_(oit.nod()); @@ -538,7 +658,8 @@ namespace rexy{ --other.m_size; } template - REXY_CPP20_CONSTEXPR void list::splice(const_iterator pos, list&& other, const_iterator first, const_iterator last){ + REXY_CPP20_CONSTEXPR + void list::splice(const_iterator pos, list&& other, const_iterator first, const_iterator last)noexcept{ for(auto oit = first;oit != last;){ auto onext = oit.next(); splice(pos, std::move(other), oit); @@ -547,7 +668,11 @@ namespace rexy{ } template - REXY_CPP20_CONSTEXPR auto list::remove(const_reference value) -> size_type{ + REXY_CPP20_CONSTEXPR + auto list::remove(const_reference value)noexcept( + std::is_nothrow_destructible_v && + is_nothrow_allocator_v) -> size_type + { return remove_if( [&value](const_reference r) -> bool{ return r == value; @@ -556,7 +681,11 @@ namespace rexy{ } template template - REXY_CPP20_CONSTEXPR auto list::remove_if(UnaryPred pred) -> size_type{ + REXY_CPP20_CONSTEXPR + auto list::remove_if(UnaryPred pred)noexcept( + std::is_nothrow_destructible_v && + is_nothrow_allocator_v) -> size_type + { size_type count = 0; for(auto it = begin();it != end();){ if(pred(*it)){ @@ -570,7 +699,8 @@ namespace rexy{ } template - REXY_CPP20_CONSTEXPR void list::reverse(void)noexcept{ + REXY_CPP20_CONSTEXPR + void list::reverse(void)noexcept{ auto* it = begin().nod(); std::swap(m_sentinel.next, m_sentinel.prev); @@ -580,7 +710,11 @@ namespace rexy{ } template - REXY_CPP20_CONSTEXPR auto list::unique(void) -> size_type{ + REXY_CPP20_CONSTEXPR + auto list::unique(void)noexcept( + std::is_nothrow_destructible_v && + is_nothrow_allocator_v) -> size_type + { return unique( [](const_reference first, const_reference second) -> bool{ return first == second; @@ -589,7 +723,11 @@ namespace rexy{ } template template - REXY_CPP20_CONSTEXPR auto list::unique(BinaryPred pred) -> size_type{ + REXY_CPP20_CONSTEXPR + auto list::unique(BinaryPred pred)noexcept( + std::is_nothrow_destructible_v && + is_nothrow_allocator_v) -> size_type + { size_type count = 0; for(auto it = begin();it != end();++it){ auto next = it.next(); @@ -602,20 +740,54 @@ namespace rexy{ } template - REXY_CPP20_CONSTEXPR void list::sort(void){ + REXY_CPP20_CONSTEXPR + void list::sort(void)noexcept{ mergesort(begin(), m_size, [](const_reference first, const_reference second)->bool{ return first < second; }); } template template - REXY_CPP20_CONSTEXPR void list::sort(Comp comp){ + REXY_CPP20_CONSTEXPR + void list::sort(Comp comp)noexcept{ mergesort(begin(), m_size, comp); } + template + template + REXY_CPP20_CONSTEXPR + void list::iterator_initialize_(InputIt first, InputIt last)noexcept( + std::is_nothrow_constructible_v && + is_nothrow_allocator_v) + { + for(;first != last;++first){ + emplace_back(*first); + } + } + template + REXY_CPP20_CONSTEXPR + void list::constant_initialize_(size_type count, const_reference value)noexcept( + std::is_nothrow_copy_constructible_v && + is_nothrow_allocator_v) + { + for(;count > 0;--count){ + emplace_back(value); + } + } + template + REXY_CPP20_CONSTEXPR + void list::default_initialize_(size_type count)noexcept( + std::is_nothrow_default_constructible_v && + is_nothrow_allocator_v) + { + for(;count > 0;--count){ + emplace_back(); + } + } + template template - auto list::mergesort(iterator first, size_type firstlen, Comp comp) -> iterator{ + auto list::mergesort(iterator first, size_type firstlen, Comp comp)noexcept -> iterator{ if(firstlen == 1) return first; auto [second, secondlen] = ms_split(first, firstlen); @@ -651,7 +823,7 @@ namespace rexy{ } template - auto list::ms_split(iterator it, size_type len) -> std::pair{ + auto list::ms_split(iterator it, size_type len)noexcept -> std::pair{ size_type second_half_len = len / 2; size_type dist = len - second_half_len; for(auto i = dist;i > 0;--i){ @@ -661,19 +833,19 @@ namespace rexy{ } template - void list::insert_node_(detail::list_node_base* prev, detail::list_node_base* n){ + void list::insert_node_(detail::list_node_base* prev, detail::list_node_base* n)noexcept{ n->next = prev->next; n->prev = prev; prev->next->prev = n; prev->next = n; } template - void list::remove_node_(detail::list_node_base* rm){ + void list::remove_node_(detail::list_node_base* rm)noexcept{ rm->prev->next = rm->next; rm->next->prev = rm->prev; } template - detail::list_node_base* list::get_next_then_move_node_(detail::list_node_base* dest, detail::list_node_base* n){ + detail::list_node_base* list::get_next_then_move_node_(detail::list_node_base* dest, detail::list_node_base* n)noexcept{ auto* next = n->next; remove_node_(n); insert_node_(dest, n); diff --git a/include/rexy/string_base.hpp b/include/rexy/string_base.hpp index 8933fe7..272abde 100644 --- a/include/rexy/string_base.hpp +++ b/include/rexy/string_base.hpp @@ -24,7 +24,6 @@ #include //std::size_t,ptrdiff #include //CHAR_BIT #include //reverse_iterator -#include //ostream #include #include "steal.hpp" @@ -526,12 +525,4 @@ namespace rexy{ #include "string_base.tpp" -namespace{ - template - std::ostream& operator<<(std::ostream& os, const rexy::basic_string& str){ - return os << str.c_str(); - } - -} - #endif