From 8ab328fcfe76ca4d9c23a5d9e29cd54353679492 Mon Sep 17 00:00:00 2001 From: rexy712 Date: Wed, 8 Jun 2022 12:09:52 -0700 Subject: [PATCH 1/3] Make string_view trivially copy-able and trivially move-able. Add wstring alias for basic_string. Add constexpr version of 'abs' function. --- include/rexy/string.hpp | 1 + include/rexy/string_base.hpp | 2 +- include/rexy/string_view.hpp | 20 ++++++++++++++------ include/rexy/string_view.tpp | 22 ---------------------- include/rexy/utility.hpp | 4 ++++ 5 files changed, 20 insertions(+), 29 deletions(-) diff --git a/include/rexy/string.hpp b/include/rexy/string.hpp index b5f4398..1eb95f5 100644 --- a/include/rexy/string.hpp +++ b/include/rexy/string.hpp @@ -27,6 +27,7 @@ namespace rexy{ //new allocated string using string = basic_string>; + using wstring = basic_string>; #ifndef LIBREXY_HEADER_ONLY extern template class basic_string>; diff --git a/include/rexy/string_base.hpp b/include/rexy/string_base.hpp index 611a34f..5306d77 100644 --- a/include/rexy/string_base.hpp +++ b/include/rexy/string_base.hpp @@ -241,7 +241,7 @@ namespace rexy{ //Supplies all functions that string_base can't implement - template + template> class basic_string : protected detail::hasallocator, public string_base { public: diff --git a/include/rexy/string_view.hpp b/include/rexy/string_view.hpp index 99e82dd..b6768b8 100644 --- a/include/rexy/string_view.hpp +++ b/include/rexy/string_view.hpp @@ -41,7 +41,7 @@ namespace rexy{ using const_pointer = const value_type*; using reference = value_type&; using const_reference = const value_type&; - using iterator = pointer; + using iterator = const_pointer; using const_iterator = const_pointer; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; @@ -53,31 +53,38 @@ namespace rexy{ size_type m_length = 0; public: - constexpr basic_string_view(void)noexcept; + constexpr basic_string_view(void)noexcept = default; constexpr basic_string_view(const_pointer str, size_type len)noexcept; constexpr basic_string_view(const_pointer c)noexcept; - constexpr basic_string_view(const basic_string_view& s)noexcept; + constexpr basic_string_view(const basic_string_view& s)noexcept = default; constexpr basic_string_view(const string_base& s)noexcept; - constexpr basic_string_view(basic_string_view&& s)noexcept; + constexpr basic_string_view(basic_string_view&& s)noexcept = default; template constexpr basic_string_view(InIter start, InIter fin)noexcept; REXY_CPP20_CONSTEXPR ~basic_string_view(void)noexcept = default; constexpr basic_string_view& operator=(const_pointer c)noexcept; - constexpr basic_string_view& operator=(const basic_string_view& s)noexcept; - constexpr basic_string_view& operator=(basic_string_view&&)noexcept; + constexpr basic_string_view& operator=(const basic_string_view& s)noexcept = default; + constexpr basic_string_view& operator=(basic_string_view&&)noexcept = default; //Length of string not including null terminator constexpr size_type length(void)const noexcept{return m_length;} + constexpr size_type size(void)const noexcept{return m_length;} + constexpr bool empty(void)const noexcept{return m_length == 0;} //direct access to managed pointer constexpr const_pointer c_str(void)const noexcept{return m_data;} + constexpr const_pointer data(void)const noexcept{return m_data;} constexpr const_pointer get(void)const noexcept{return m_data;} constexpr operator const_pointer(void)const noexcept{return m_data;} //true if m_data is not empty constexpr bool valid(void)const noexcept{return m_length > 0;} constexpr const_reference operator[](size_type i)const noexcept{return m_data[i];} + constexpr const_reference at(size_type i)const noexcept{return m_data[i];} + constexpr const_reference front(size_type i)const noexcept{return m_data[0];} + constexpr const_reference back(size_type i)const noexcept{return m_data[m_length-1];} + constexpr const_iterator it_at(size_type i)const noexcept{return m_data + i;} constexpr const_iterator search(const basic_string_view& s)const; constexpr const_iterator search(const_pointer c)const; @@ -115,6 +122,7 @@ namespace rexy{ basic_string_view(const T*, size_t) -> basic_string_view; using string_view = basic_string_view; + using wstring_view = basic_string_view; #ifndef LIBREXY_HEADER_ONLY extern template class basic_string_view; diff --git a/include/rexy/string_view.tpp b/include/rexy/string_view.tpp index 6c630c3..3d60398 100644 --- a/include/rexy/string_view.tpp +++ b/include/rexy/string_view.tpp @@ -25,33 +25,17 @@ namespace rexy{ - template - constexpr basic_string_view::basic_string_view(void)noexcept: - basic_string_view(nullptr, 0){} - template constexpr basic_string_view::basic_string_view(const_pointer str, size_type len)noexcept: m_data(str), m_length(len){} template - constexpr basic_string_view::basic_string_view(const basic_string_view& s)noexcept: - m_data(s.m_data), m_length(s.m_length){} - template constexpr basic_string_view::basic_string_view(const string_base& s)noexcept: m_data(s.c_str()), m_length(s.length()){} template - constexpr basic_string_view::basic_string_view(basic_string_view&& s)noexcept: - m_data(s.m_data), m_length(s.m_length){} - template template constexpr basic_string_view::basic_string_view(InIter start, InIter fin)noexcept: basic_string_view(compat::to_address(start), fin - start){} - template - constexpr basic_string_view& basic_string_view::operator=(const basic_string_view& s)noexcept{ - m_data = s.m_data; - m_length = s.m_length; - return *this; - } template constexpr basic_string_view::basic_string_view(const_pointer c)noexcept: basic_string_view(c, strlen(c)){} @@ -61,12 +45,6 @@ namespace rexy{ m_length = strlen(c); return *this; } - template - constexpr basic_string_view& basic_string_view::operator=(basic_string_view&& s)noexcept{ - m_data = s.m_data; - m_length = s.m_length; - return *this; - } template constexpr auto basic_string_view::search(const basic_string_view& s)const -> const_iterator{ diff --git a/include/rexy/utility.hpp b/include/rexy/utility.hpp index a9cbb77..a1d063c 100644 --- a/include/rexy/utility.hpp +++ b/include/rexy/utility.hpp @@ -106,6 +106,10 @@ namespace rexy{ ld[i] = rd[i]; } } + template + constexpr T abs(const T& val){ + return val > 0 ? val : val; + } } } From e96899cebae72af8d633bd503bdff059ae4d9ace Mon Sep 17 00:00:00 2001 From: rexy712 Date: Wed, 8 Jun 2022 16:06:24 -0700 Subject: [PATCH 2/3] Fixed abs just not doing anything --- include/rexy/utility.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/rexy/utility.hpp b/include/rexy/utility.hpp index a1d063c..6299632 100644 --- a/include/rexy/utility.hpp +++ b/include/rexy/utility.hpp @@ -108,7 +108,7 @@ namespace rexy{ } template constexpr T abs(const T& val){ - return val > 0 ? val : val; + return val > 0 ? val : -val; } } From 1acce4c5882abe3f18e3921ef64b366aa78cfa10 Mon Sep 17 00:00:00 2001 From: rexy712 Date: Wed, 8 Jun 2022 19:21:49 -0700 Subject: [PATCH 3/3] Add is_nothrow_allocator type trait --- include/rexy/allocator.hpp | 9 +++++ include/rexy/detail/hasallocator.hpp | 18 ++++----- include/rexy/string_base.hpp | 59 ++++++++++++---------------- include/rexy/string_base.tpp | 58 +++++++++++---------------- 4 files changed, 67 insertions(+), 77 deletions(-) diff --git a/include/rexy/allocator.hpp b/include/rexy/allocator.hpp index 2bfda3b..3272898 100644 --- a/include/rexy/allocator.hpp +++ b/include/rexy/allocator.hpp @@ -38,6 +38,8 @@ #include "rexy.hpp" #include "compat/standard.hpp" +#include //declval + namespace rexy{ template @@ -170,6 +172,13 @@ namespace rexy{ return false; } + template + struct is_nothrow_allocator{ + static constexpr bool value = noexcept(std::declval().allocate(0)) && noexcept(std::declval().deallocate(nullptr, 0)); + }; + template + static constexpr bool is_nothrow_allocator_v = is_nothrow_allocator::value; + } #endif diff --git a/include/rexy/detail/hasallocator.hpp b/include/rexy/detail/hasallocator.hpp index 34a7731..9182496 100644 --- a/include/rexy/detail/hasallocator.hpp +++ b/include/rexy/detail/hasallocator.hpp @@ -31,17 +31,17 @@ namespace rexy::detail{ { Alloc m_alloc; - REXY_CPP20_CONSTEXPR auto allocate(typename Alloc::size_type bytes)noexcept(noexcept(m_alloc.allocate(0))){ + REXY_CPP20_CONSTEXPR auto allocate(typename Alloc::size_type bytes)noexcept(is_nothrow_allocator_v){ return m_alloc.allocate(bytes); } - REXY_CPP20_CONSTEXPR void deallocate(typename Alloc::pointer p, typename Alloc::size_type bytes)noexcept(noexcept(m_alloc.deallocate(nullptr,0))){ + REXY_CPP20_CONSTEXPR void deallocate(typename Alloc::pointer p, typename Alloc::size_type bytes)noexcept(is_nothrow_allocator_v){ m_alloc.deallocate(p, bytes); } - Alloc& allocator(void){ + constexpr Alloc& allocator(void){ return m_alloc; } - const Alloc& allocator(void)const{ + constexpr const Alloc& allocator(void)const{ return m_alloc; } }; @@ -52,21 +52,21 @@ namespace rexy::detail{ [[no_unique_address]] Alloc m_alloc; - REXY_CPP20_CONSTEXPR auto allocate(typename Alloc::size_type bytes)noexcept(noexcept(m_alloc.allocate(0))){ + REXY_CPP20_CONSTEXPR auto allocate(typename Alloc::size_type bytes)noexcept(is_nothrow_allocator_v){ return m_alloc.allocate(bytes); } - REXY_CPP20_CONSTEXPR void deallocate(typename Alloc::pointer p, typename Alloc::size_type bytes)noexcept(noexcept(m_alloc.deallocate(nullptr,0))){ + REXY_CPP20_CONSTEXPR void deallocate(typename Alloc::pointer p, typename Alloc::size_type bytes)noexcept(is_nothrow_allocator_v){ m_alloc.deallocate(p, bytes); } - Alloc& allocator(void){ + constexpr Alloc& allocator(void){ return m_alloc; } - const Alloc& allocator(void)const{ + constexpr const Alloc& allocator(void)const{ return m_alloc; } }; -#endif +#endif //no_unique_address } #endif diff --git a/include/rexy/string_base.hpp b/include/rexy/string_base.hpp index 5306d77..6b13a1a 100644 --- a/include/rexy/string_base.hpp +++ b/include/rexy/string_base.hpp @@ -33,6 +33,7 @@ #include "expression.hpp" #include "detail/string_appender.hpp" #include "detail/hasallocator.hpp" +#include "allocator.hpp" #include "rexy.hpp" #include "compat/standard.hpp" @@ -260,74 +261,64 @@ namespace rexy{ private: REXY_CPP20_CONSTEXPR void _copy_construct_string(const_pointer data, size_type len, size_type cap) - noexcept(noexcept(this->allocate(0))); + noexcept(is_nothrow_allocator_v); REXY_CPP20_CONSTEXPR basic_string& _copy_string(const_pointer s, size_type len) - noexcept(noexcept(this->allocate(0)) && - noexcept(this->deallocate(nullptr,0))); + noexcept(is_nothrow_allocator_v); public: constexpr basic_string(void)noexcept; constexpr basic_string(rexy::steal data, size_type len)noexcept; constexpr basic_string(rexy::steal data, size_type len, size_type cap)noexcept; constexpr basic_string(rexy::steal data)noexcept; - REXY_CPP20_CONSTEXPR basic_string(const_pointer data, size_type len)noexcept(noexcept(this->allocate(0))); - REXY_CPP20_CONSTEXPR basic_string(const_pointer data, size_type len, size_type cap)noexcept(noexcept(this->allocate(0))); - REXY_CPP20_CONSTEXPR basic_string(const_pointer data)noexcept(noexcept(this->allocate(0))); - REXY_CPP20_CONSTEXPR explicit basic_string(size_type len)noexcept(noexcept(this->allocate(0))); - REXY_CPP20_CONSTEXPR basic_string(size_type len, size_type cap)noexcept(noexcept(this->allocate(0))); + REXY_CPP20_CONSTEXPR basic_string(const_pointer data, size_type len)noexcept(is_nothrow_allocator_v); + REXY_CPP20_CONSTEXPR basic_string(const_pointer data, size_type len, size_type cap)noexcept(is_nothrow_allocator_v); + REXY_CPP20_CONSTEXPR basic_string(const_pointer data)noexcept(is_nothrow_allocator_v); + REXY_CPP20_CONSTEXPR explicit basic_string(size_type len)noexcept(is_nothrow_allocator_v); + REXY_CPP20_CONSTEXPR basic_string(size_type len, size_type cap)noexcept(is_nothrow_allocator_v); template - REXY_CPP20_CONSTEXPR basic_string(InputIt start, InputIt fin)noexcept(noexcept(this->allocate(0))); - REXY_CPP20_CONSTEXPR basic_string(const basic_string_view& sv)noexcept(noexcept(this->allocate(0))); + REXY_CPP20_CONSTEXPR basic_string(InputIt start, InputIt fin)noexcept(is_nothrow_allocator_v); + REXY_CPP20_CONSTEXPR basic_string(const basic_string_view& sv)noexcept(is_nothrow_allocator_v); //normal copy and move ctors - REXY_CPP20_CONSTEXPR basic_string(const basic_string& b)noexcept(noexcept(this->allocate(0))); + REXY_CPP20_CONSTEXPR basic_string(const basic_string& b)noexcept(is_nothrow_allocator_v); constexpr basic_string(basic_string&& s)noexcept; - REXY_CPP20_CONSTEXPR basic_string(const string_base&)noexcept(noexcept(this->allocate(0))); + REXY_CPP20_CONSTEXPR basic_string(const string_base&)noexcept(is_nothrow_allocator_v); //dtor - REXY_CPP20_CONSTEXPR ~basic_string(void)noexcept(noexcept(this->deallocate(nullptr, 0))); + REXY_CPP20_CONSTEXPR ~basic_string(void)noexcept(is_nothrow_allocator_v); REXY_CPP20_CONSTEXPR basic_string& operator=(const basic_string& s) - noexcept(noexcept(this->allocate(0)) && - noexcept(this->deallocate(nullptr,0))); + noexcept(is_nothrow_allocator_v); constexpr basic_string& operator=(basic_string&& s)noexcept; REXY_CPP20_CONSTEXPR basic_string& operator=(const string_base& s) - noexcept(noexcept(this->allocate(0)) && - noexcept(this->deallocate(nullptr,0))); + noexcept(is_nothrow_allocator_v); REXY_CPP20_CONSTEXPR basic_string& operator=(const basic_string_view& sv) - noexcept(noexcept(this->allocate(0)) && - noexcept(this->deallocate(nullptr,0))); + noexcept(is_nothrow_allocator_v); //Copy from c string REXY_CPP20_CONSTEXPR basic_string& operator=(const_pointer c) - noexcept(noexcept(this->allocate(0)) && - noexcept(this->deallocate(nullptr,0))); + noexcept(is_nothrow_allocator_v); //Replace managed pointer. Frees existing value - REXY_CPP20_CONSTEXPR void reset(pointer val = nullptr)noexcept(noexcept(this->deallocate(nullptr,0))); - REXY_CPP20_CONSTEXPR void reset(pointer val, size_type len)noexcept(noexcept(this->deallocate(nullptr,0))); + REXY_CPP20_CONSTEXPR void reset(pointer val = nullptr)noexcept(is_nothrow_allocator_v); + REXY_CPP20_CONSTEXPR void reset(pointer val, size_type len)noexcept(is_nothrow_allocator_v); REXY_CPP20_CONSTEXPR bool resize(size_type newsize) - noexcept(noexcept(this->allocate(0)) && - noexcept(this->deallocate(nullptr,0))); + noexcept(is_nothrow_allocator_v); REXY_CPP20_CONSTEXPR void push_back(value_type data) - noexcept(noexcept(this->allocate(0)) && - noexcept(this->deallocate(nullptr,0))); + noexcept(is_nothrow_allocator_v); REXY_CPP20_CONSTEXPR void append(const_pointer data, size_type len) - noexcept(noexcept(this->allocate(0)) && - noexcept(this->deallocate(nullptr,0))); + noexcept(is_nothrow_allocator_v); REXY_CPP20_CONSTEXPR void append(const_pointer data) - noexcept(noexcept(this->allocate(0)) && - noexcept(this->deallocate(nullptr,0))); + noexcept(is_nothrow_allocator_v); template REXY_CPP20_CONSTEXPR void append(InputIt start, InputIt fin) - noexcept(noexcept(this->allocate(0)) && - noexcept(this->deallocate(nullptr,0))); + noexcept(is_nothrow_allocator_v); template REXY_CPP20_CONSTEXPR basic_string substring(size_type start, size_type end)const; - REXY_CPP20_CONSTEXPR pointer release(void)noexcept(noexcept(this->allocate(0))); + REXY_CPP20_CONSTEXPR pointer release(void)noexcept(is_nothrow_allocator_v); using detail::hasallocator::allocator; constexpr basic_string_view create_view(void)const noexcept; diff --git a/include/rexy/string_base.tpp b/include/rexy/string_base.tpp index a6c6bc0..8d228e0 100644 --- a/include/rexy/string_base.tpp +++ b/include/rexy/string_base.tpp @@ -82,7 +82,7 @@ namespace rexy{ //allocate string if longer than small string capacity, copy otherwise template REXY_CPP20_CONSTEXPR void basic_string::_copy_construct_string(const_pointer data, size_type len, size_type cap) - noexcept(noexcept(this->allocate(0))) + noexcept(is_nothrow_allocator_v) { if(cap > this->get_short_capacity()){ this->set_islong_flag(true); @@ -116,31 +116,31 @@ namespace rexy{ string_base(data.value(), len, cap){} template REXY_CPP20_CONSTEXPR basic_string::basic_string(const_pointer data, size_type len, size_type cap) - noexcept(noexcept(this->allocate(0))) + noexcept(is_nothrow_allocator_v) { _copy_construct_string(data, len, cap); } template REXY_CPP20_CONSTEXPR basic_string::basic_string(const_pointer data, size_type len) - noexcept(noexcept(this->allocate(0))): + noexcept(is_nothrow_allocator_v): basic_string(data, len, len){} template REXY_CPP20_CONSTEXPR basic_string::basic_string(const_pointer data) - noexcept(noexcept(this->allocate(0))): + noexcept(is_nothrow_allocator_v): basic_string(data, data ? strlen(data) : 0){} template REXY_CPP20_CONSTEXPR basic_string::basic_string(size_type cap) - noexcept(noexcept(this->allocate(0))): + noexcept(is_nothrow_allocator_v): basic_string(size_type{0}, cap){} template REXY_CPP20_CONSTEXPR basic_string::basic_string(size_type len, size_type cap) - noexcept(noexcept(this->allocate(0))) + noexcept(is_nothrow_allocator_v) { _copy_construct_string(nullptr, len, cap); } template REXY_CPP20_CONSTEXPR basic_string::basic_string(const basic_string_view& sv) - noexcept(noexcept(this->allocate(0))) + noexcept(is_nothrow_allocator_v) { _copy_construct_string(sv.c_str(), sv.length(), sv.length()); } @@ -148,7 +148,7 @@ namespace rexy{ template template REXY_CPP20_CONSTEXPR basic_string::basic_string(InputIt start, InputIt fin) - noexcept(noexcept(this->allocate(0))): + noexcept(is_nothrow_allocator_v): basic_string(nullptr, size_type{fin - start}) { auto raw = this->get_pointer(); @@ -161,7 +161,7 @@ namespace rexy{ //normal copy and move ctors template REXY_CPP20_CONSTEXPR basic_string::basic_string(const basic_string& b) - noexcept(noexcept(this->allocate(0))): + noexcept(is_nothrow_allocator_v): detail::hasallocator(b) { _copy_construct_string(b.get(), b.length(), b.capacity()); @@ -172,7 +172,7 @@ namespace rexy{ string_base(std::move(s)){} template REXY_CPP20_CONSTEXPR basic_string::basic_string(const string_base& b) - noexcept(noexcept(this->allocate(0))) + noexcept(is_nothrow_allocator_v) { _copy_construct_string(b.get(), b.length(), b.capacity()); } @@ -180,7 +180,7 @@ namespace rexy{ //dtor template REXY_CPP20_CONSTEXPR basic_string::~basic_string(void) - noexcept(noexcept(this->deallocate(nullptr, 0))) + noexcept(is_nothrow_allocator_v) { if(this->islong()){ this->deallocate(this->get_pointer(), sizeof(value_type)*(this->get_long_capacity()+1)); @@ -189,8 +189,7 @@ namespace rexy{ template REXY_CPP20_CONSTEXPR basic_string& basic_string::operator=(const basic_string& s) - noexcept(noexcept(this->allocate(0)) && - noexcept(this->deallocate(nullptr, 0))) + noexcept(is_nothrow_allocator_v) { if(s.length() < this->capacity()){ memcpy(this->get_pointer(), s.get_pointer(), sizeof(value_type)*(s.length()+1)); @@ -207,24 +206,21 @@ namespace rexy{ } template REXY_CPP20_CONSTEXPR basic_string& basic_string::operator=(const string_base& s) - noexcept(noexcept(this->allocate(0)) && - noexcept(this->deallocate(nullptr,0))) + noexcept(is_nothrow_allocator_v) { return (*this = basic_string(s)); } //Copy from c string template REXY_CPP20_CONSTEXPR basic_string& basic_string::operator=(const basic_string_view& sv) - noexcept(noexcept(this->allocate(0)) && - noexcept(this->deallocate(nullptr,0))) + noexcept(is_nothrow_allocator_v) { return _copy_string(sv.c_str(), sv.length()); } template REXY_CPP20_CONSTEXPR basic_string& basic_string::operator=(const_pointer c) - noexcept(noexcept(this->allocate(0)) && - noexcept(this->deallocate(nullptr,0))) + noexcept(is_nothrow_allocator_v) { return _copy_string(c, strlen(c)); } @@ -232,13 +228,13 @@ namespace rexy{ //Replace managed pointer. Frees existing value template REXY_CPP20_CONSTEXPR void basic_string::reset(pointer val) - noexcept(noexcept(this->deallocate(nullptr,0))) + noexcept(is_nothrow_allocator_v) { reset(val, val ? strlen(val) : 0); } template REXY_CPP20_CONSTEXPR void basic_string::reset(pointer val, size_type len) - noexcept(noexcept(this->deallocate(nullptr,0))) + noexcept(is_nothrow_allocator_v) { if(this->islong()) this->deallocate(this->get_long_ptr(),sizeof(value_type)*(this->get_long_capacity()+1)); @@ -249,8 +245,7 @@ namespace rexy{ } template REXY_CPP20_CONSTEXPR bool basic_string::resize(size_type newsize) - noexcept(noexcept(this->allocate(0)) && - noexcept(this->deallocate(nullptr,0))) + noexcept(is_nothrow_allocator_v) { if(newsize < this->capacity()) return false; @@ -261,16 +256,14 @@ namespace rexy{ template REXY_CPP20_CONSTEXPR void basic_string::push_back(value_type data) - noexcept(noexcept(this->allocate(0)) && - noexcept(this->deallocate(nullptr,0))) + noexcept(is_nothrow_allocator_v) { append(&data, 1); } template REXY_CPP20_CONSTEXPR void basic_string::append(const_pointer data, size_type len) - noexcept(noexcept(this->allocate(0)) && - noexcept(this->deallocate(nullptr,0))) + noexcept(is_nothrow_allocator_v) { size_type mylen = this->length(); size_type mycap = this->capacity(); @@ -290,8 +283,7 @@ namespace rexy{ } template REXY_CPP20_CONSTEXPR void basic_string::append(const_pointer data) - noexcept(noexcept(this->allocate(0)) && - noexcept(this->deallocate(nullptr,0))) + noexcept(is_nothrow_allocator_v) { if(data) append(data, strlen(data)); @@ -299,8 +291,7 @@ namespace rexy{ template template REXY_CPP20_CONSTEXPR void basic_string::append(InputIt start, InputIt fin) - noexcept(noexcept(this->allocate(0)) && - noexcept(this->deallocate(nullptr,0))) + noexcept(is_nothrow_allocator_v) { size_type append_len = fin - start; @@ -334,7 +325,7 @@ namespace rexy{ return tmp; } template - REXY_CPP20_CONSTEXPR auto basic_string::release(void)noexcept(noexcept(this->allocate(0))) -> pointer{ + REXY_CPP20_CONSTEXPR auto basic_string::release(void)noexcept(is_nothrow_allocator_v) -> pointer{ if(this->islong()){ pointer raw = this->get_long_ptr(); this->set_islong_flag(false); @@ -363,8 +354,7 @@ namespace rexy{ template REXY_CPP20_CONSTEXPR basic_string& basic_string::_copy_string(const_pointer s, size_type len) - noexcept(noexcept(this->allocate(0)) && - noexcept(this->deallocate(nullptr,0))) + noexcept(is_nothrow_allocator_v) { if(!s || !len) return (*this = basic_string(rexy::steal(nullptr), 0, 0));