diff --git a/doc/container.qbk b/doc/container.qbk index 6418f48..f4e5824 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1462,7 +1462,8 @@ use [*Boost.Container]? There are several reasons for that: * Updated `basic_string`: * Added missing `string_view` members and updated `operator[]` to be able to return the terminating null. * Added C++20 `starts_with`/`ends_with` and C++23 `contains` overloads. - * Added Clang `nullability` checks for `basic_string` methods. + * Added null pointer checks for `basic_string` methods taking `const CharT*` parameters. + * Deleted constructor from `std::nullptr_t`. * Fixed bugs/issues: * [@https://github.com/boostorg/container/issues/323 GitHub #323: ['"flat_tree::try_emplace UB"]]. * [@https://github.com/boostorg/container/issues/328 GitHub #328: ['"boost::container::deque stores a redundant copy of the allocator, increasing size"]]. diff --git a/include/boost/container/detail/workaround.hpp b/include/boost/container/detail/workaround.hpp index 15f1beb..a93f69f 100644 --- a/include/boost/container/detail/workaround.hpp +++ b/include/boost/container/detail/workaround.hpp @@ -252,18 +252,4 @@ namespace boost { #define BOOST_CONTAINER_NOVTABLE #endif -#if defined(__has_feature) -# if __has_feature(nullability) -# define BOOST_CONTAINER_NONNULL_SUPPORTED -# define BOOST_CONTAINER_NONNULL _Nonnull -# define BOOST_CONTAINER_NULLABLE _Nullable -# endif -#endif - -#if !defined(BOOST_CONTAINER_NONNULL_SUPPORTED) -# define BOOST_CONTAINER_NONNULL -# define BOOST_CONTAINER_NULLABLE -# undef BOOST_CONTAINER_NONNULL_SUPPORTED -#endif - #endif //#ifndef BOOST_CONTAINER_DETAIL_WORKAROUND_HPP diff --git a/include/boost/container/string.hpp b/include/boost/container/string.hpp index 9b8cf66..736ad93 100644 --- a/include/boost/container/string.hpp +++ b/include/boost/container/string.hpp @@ -240,16 +240,16 @@ class basic_string_base : allocator_type(boost::forward(a)) { this->init(); } - inline const short_t * BOOST_CONTAINER_NONNULL pshort_repr() const + inline const short_t * pshort_repr() const { return move_detail::launder_cast(&m_repr); } - inline const long_t * BOOST_CONTAINER_NONNULL plong_repr() const + inline const long_t * plong_repr() const { return move_detail::launder_cast(&m_repr); } - inline short_t *BOOST_CONTAINER_NONNULL pshort_repr() + inline short_t * pshort_repr() { return move_detail::launder_cast(&m_repr); } - inline long_t *BOOST_CONTAINER_NONNULL plong_repr() + inline long_t * plong_repr() { return move_detail::launder_cast(&m_repr); } repr_t m_repr; @@ -278,7 +278,7 @@ class basic_string_base return hdr.is_short != 0; } - inline short_t *BOOST_CONTAINER_NONNULL construct_short() + inline short_t * construct_short() { short_t *ps = ::new(&this->members_.m_repr) short_t; ps->h.is_short = 1; @@ -291,7 +291,7 @@ class basic_string_base this->members_.pshort_repr()->~short_t(); } - short_t *BOOST_CONTAINER_NONNULL assure_short() + short_t * assure_short() { if (!this->is_short()){ this->destroy_long(); @@ -300,7 +300,7 @@ class basic_string_base return this->members_.pshort_repr(); } - inline long_t *BOOST_CONTAINER_NONNULL construct_long() + inline long_t * construct_long() { long_t *pl = ::new(&this->members_.m_repr) long_t; //is_short flag is written in the constructor @@ -313,7 +313,7 @@ class basic_string_base this->members_.plong_repr()->~long_t(); } - long_t *BOOST_CONTAINER_NONNULL assure_long() + long_t * assure_long() { if (this->is_short()){ this->destroy_short(); @@ -590,10 +590,10 @@ class basic_string typedef bool result_type; typedef const typename Tr::char_type* Pointer; - const Pointer BOOST_CONTAINER_NONNULL m_first; - const Pointer BOOST_CONTAINER_NONNULL m_last; + const Pointer m_first; + const Pointer m_last; - Not_within_traits(Pointer BOOST_CONTAINER_NONNULL f, Pointer BOOST_CONTAINER_NONNULL l) + Not_within_traits(Pointer f, Pointer l) : m_first(f), m_last(l) {} bool operator()(const typename Tr::char_type& x) const @@ -655,6 +655,10 @@ class basic_string , n + 1) { this->priv_terminate_string(); } + #if !defined( BOOST_NO_CXX11_NULLPTR ) + BOOST_DELETED_FUNCTION(basic_string( decltype(nullptr) )) + #endif //!defined( BOOST_NO_CXX11_NULLPTR ) + #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED //! Effects: Default constructs a basic_string. @@ -769,36 +773,38 @@ class basic_string //! Effects: Constructs a basic_string taking a default-constructed allocator, //! and is initialized by a specific number of characters of the s c-string. - basic_string(const CharT* BOOST_CONTAINER_NONNULL s, size_type n) + basic_string(const CharT* s, size_type n) : base_t() { this->priv_terminate_string(); - this->assign(s, s + difference_type(n)); + this->assign(s, n); // assign checks for s != 0 } //! Effects: Constructs a basic_string taking the allocator as parameter, //! and is initialized by a specific number of characters of the s c-string. - basic_string(const CharT* BOOST_CONTAINER_NONNULL s, size_type n, const allocator_type& a) + basic_string(const CharT* s, size_type n, const allocator_type& a) : base_t(a) { this->priv_terminate_string(); - this->assign(s, s + difference_type(n)); + this->assign(s, n); // assign checks for s != 0 } //! Effects: Constructs a basic_string with a default-constructed allocator, //! and is initialized by the null-terminated s c-string. - basic_string(const CharT* BOOST_CONTAINER_NONNULL s) + basic_string(const CharT* s) : base_t() { + BOOST_ASSERT(s != 0); this->priv_terminate_string(); this->assign(s, s + Traits::length(s)); } //! Effects: Constructs a basic_string taking the allocator as parameter, //! and is initialized by the null-terminated s c-string. - basic_string(const CharT* BOOST_CONTAINER_NONNULL s, const allocator_type& a) + basic_string(const CharT* s, const allocator_type& a) : base_t(a) { + BOOST_ASSERT(s != 0); this->priv_terminate_string(); this->assign(s, s + Traits::length(s)); } @@ -931,8 +937,10 @@ class basic_string //! Effects: Assignment from a null-terminated c-string. //! - basic_string& operator=(const CharT* BOOST_CONTAINER_NONNULL s) - { return this->assign(s, s + Traits::length(s)); } + basic_string& operator=(const CharT* s) + { + return this->assign(s); // assign checks for s != 0 + } //! Effects: Returns *this = basic_string(1, c). //! @@ -1391,8 +1399,10 @@ class basic_string //! Effects: Calls append(s). //! //! Returns: *this - basic_string& operator+=(const CharT* BOOST_CONTAINER_NONNULL s) - { return this->append(s); } + basic_string& operator+=(const CharT* s) + { + return this->append(s); //append checks for s != 0 + } //! Effects: Calls append(1, c). //! @@ -1464,16 +1474,22 @@ class basic_string //! Throws: If memory allocation throws length_error if size() + n > max_size(). //! //! Returns: *this - basic_string& append(const CharT* BOOST_CONTAINER_NONNULL s, size_type n) - { return this->append(s, s + difference_type(n)); } + basic_string& append(const CharT* s, size_type n) + { + BOOST_ASSERT(s != 0); + return this->append(s, s + difference_type(n)); + } //! Requires: s points to an array of at least traits::length(s) + 1 elements of CharT. //! //! Effects: Calls append(s, traits::length(s)). //! //! Returns: *this - basic_string& append(const CharT* BOOST_CONTAINER_NONNULL s) - { return this->append(s, s + Traits::length(s)); } + basic_string& append(const CharT* s) + { + BOOST_ASSERT(s != 0); + return this->append(s, s + Traits::length(s)); + } //! Effects: Equivalent to append(basic_string(n, c)). //! @@ -1491,11 +1507,11 @@ class basic_string { this->insert(this->end(), first, last); return *this; } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) - //! Effects: Returns append(il.begin(), il.size()). + //! Effects: Returns append(il.begin(), il.end()). //! basic_string& append(std::initializer_list il) { - return this->append(il.begin(), il.size()); + return this->append(il.begin(), il.end()); } #endif @@ -1576,16 +1592,22 @@ class basic_string //! Throws: If memory allocation throws or length_error if n > max_size(). //! //! Returns: *this - basic_string& assign(const CharT* BOOST_CONTAINER_NONNULL s, size_type n) - { return this->assign(s, s + difference_type(n)); } + basic_string& assign(const CharT* s, size_type n) + { + BOOST_ASSERT(s != 0); + return this->assign(s, s + difference_type(n)); + } //! Requires: s points to an array of at least traits::length(s) + 1 elements of CharT. //! //! Effects: Calls assign(s, traits::length(s)). //! //! Returns: *this - basic_string& assign(const CharT* BOOST_CONTAINER_NONNULL s) - { return this->assign(s, s + Traits::length(s)); } + basic_string& assign(const CharT* s) + { + BOOST_ASSERT(s != 0); + return this->assign(s, s + Traits::length(s)); + } //! Effects: Equivalent to assign(basic_string(n, c)). //! @@ -1596,11 +1618,11 @@ class basic_string //! Effects: Equivalent to assign(basic_string(first, last)). //! //! Returns: *this - basic_string& assign(const CharT* BOOST_CONTAINER_NULLABLE first, const CharT* BOOST_CONTAINER_NULLABLE last) + basic_string& assign(const CharT* first, const CharT* last) { size_type n = static_cast(last - first); this->reserve(n); - CharT* BOOST_CONTAINER_NONNULL ptr = boost::movelib::to_raw_pointer(this->priv_addr()); + CharT* const ptr = boost::movelib::to_raw_pointer(this->priv_addr()); Traits::copy(ptr, first, n); this->priv_construct_null(ptr + difference_type(n)); this->priv_size(n); @@ -1613,7 +1635,7 @@ class basic_string template basic_string& assign(InputIter first, InputIter last #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - , typename dtl::disable_if_convertible::type * BOOST_CONTAINER_NULLABLE = 0 + , typename dtl::disable_if_convertible::type * = 0 #endif ) { @@ -1635,11 +1657,11 @@ class basic_string } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) - //! Effects: Returns assign(il.begin(), il.size()). + //! Effects: Returns assign(il.begin(), il.end()). //! basic_string& assign(std::initializer_list il) { - return this->assign(il.begin(), il.size()); + return this->assign(il.begin(), il.end()); } #endif @@ -1695,8 +1717,9 @@ class basic_string //! length_error if size() + n > max_size(). //! //! Returns: *this - basic_string& insert(size_type pos, const CharT* BOOST_CONTAINER_NONNULL s, size_type n) + basic_string& insert(size_type pos, const CharT* s, size_type n) { + BOOST_ASSERT(s != 0); if (pos > this->size()) throw_out_of_range("basic_string::insert out of range position"); if (this->size() > this->max_size() - n) @@ -1713,8 +1736,9 @@ class basic_string //! length_error if size() > max_size() - Traits::length(s) //! //! Returns: *this - basic_string& insert(size_type pos, const CharT* BOOST_CONTAINER_NONNULL s) + basic_string& insert(size_type pos, const CharT* s) { + BOOST_ASSERT(s != 0); if (pos > this->size()) throw_out_of_range("basic_string::insert out of range position"); size_type len = Traits::length(s); @@ -1803,7 +1827,7 @@ class basic_string < void , dtl::is_convertible , dtl::is_not_input_iterator - >::type * BOOST_CONTAINER_NULLABLE = 0 + >::type * = 0 #endif ) { @@ -1821,7 +1845,7 @@ class basic_string < void , dtl::is_convertible , dtl::is_input_iterator - >::type * BOOST_CONTAINER_NULLABLE = 0 + >::type * = 0 ) { const size_type n_pos = size_type(p - this->cbegin()); @@ -2106,8 +2130,9 @@ class basic_string //! if the length of the resulting string would exceed max_size() //! //! Returns: *this - basic_string& replace(size_type pos1, size_type n1, const CharT* BOOST_CONTAINER_NONNULL s, size_type n2) + basic_string& replace(size_type pos1, size_type n1, const CharT* s, size_type n2) { + BOOST_ASSERT(s != 0); if (pos1 > this->size()) throw_out_of_range("basic_string::replace out of range position"); const size_type len = dtl::min_value(n1, this->size() - pos1); @@ -2132,8 +2157,9 @@ class basic_string //! if the length of the resulting string would exceed max_size() //! //! Returns: *this - inline basic_string& replace(size_type pos, size_type n1, const CharT* BOOST_CONTAINER_NONNULL s) + inline basic_string& replace(size_type pos, size_type n1, const CharT* s) { + BOOST_ASSERT(s != 0); return this->replace(pos, n1, s, Traits::length(s)); } @@ -2174,8 +2200,11 @@ class basic_string //! Throws: if memory allocation throws //! //! Returns: *this - inline basic_string& replace(const_iterator i1, const_iterator i2, const CharT* BOOST_CONTAINER_NONNULL s, size_type n) - { return this->replace(i1, i2, s, s + difference_type(n)); } + inline basic_string& replace(const_iterator i1, const_iterator i2, const CharT* s, size_type n) + { + BOOST_ASSERT(s != 0); + return this->replace(i1, i2, s, s + difference_type(n)); + } //! Requires: [begin(),i1) and [i1,i2) are valid ranges and s points to an //! array of at least traits::length(s) + 1 elements of CharT. @@ -2185,8 +2214,11 @@ class basic_string //! Throws: if memory allocation throws //! //! Returns: *this - inline basic_string& replace(const_iterator i1, const_iterator i2, const CharT* BOOST_CONTAINER_NONNULL s) - { return this->replace(i1, i2, s, s + Traits::length(s)); } + inline basic_string& replace(const_iterator i1, const_iterator i2, const CharT* s) + { + BOOST_ASSERT(s != 0); + return this->replace(i1, i2, s, s + Traits::length(s)); + } //! Requires: [begin(),i1) and [i1,i2) are valid ranges. //! @@ -2223,7 +2255,7 @@ class basic_string < void , dtl::is_convertible , dtl::is_input_iterator - >::type * BOOST_CONTAINER_NULLABLE = 0 + >::type * = 0 #endif ) { @@ -2245,7 +2277,7 @@ class basic_string < void , dtl::is_convertible , dtl::is_not_input_iterator - >::type * BOOST_CONTAINER_NULLABLE = 0 + >::type * = 0 ) { difference_type n = boost::container::iterator_distance(j1, j2); @@ -2279,14 +2311,12 @@ class basic_string #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! Requires: [begin(), i1) and [i1, i2) are valid ranges. //! - //! Effects: Calls replace(i1 - begin(), i2 - i1, il.begin(), il.size()). + //! Effects: Calls replace(i1, i2, il.begin(), il.end()). //! //! Returns: *this. inline basic_string& replace(const_iterator i1, const_iterator i2, std::initializer_list il) { - return this->replace( static_cast(i1 - this->cbegin()) - , static_cast(i2 - i1) - , il.begin(), il.size()); + return this->replace(i1, i2, il.begin(), il.end()); } #endif @@ -2301,8 +2331,9 @@ class basic_string //! Throws: if memory allocation throws, out_of_range if pos > size(). //! //! Returns: rlen - size_type copy(CharT* BOOST_CONTAINER_NONNULL s, size_type n, size_type pos = 0) const + size_type copy(CharT* s, size_type n, size_type pos = 0) const { + BOOST_ASSERT(s != 0); if (pos > this->size()) throw_out_of_range("basic_string::copy out of range position"); const size_type len = dtl::min_value(n, this->size() - pos); @@ -2335,7 +2366,7 @@ class basic_string //! //! Complexity: constant time. BOOST_CONTAINER_NODISCARD inline - const CharT* BOOST_CONTAINER_NONNULL c_str() const BOOST_NOEXCEPT_OR_NOTHROW + const CharT* c_str() const BOOST_NOEXCEPT_OR_NOTHROW { return boost::movelib::to_raw_pointer(this->priv_addr()); } //! Requires: The program shall not alter any of the values stored in the character array. @@ -2344,14 +2375,14 @@ class basic_string //! //! Complexity: constant time. BOOST_CONTAINER_NODISCARD inline - const CharT* BOOST_CONTAINER_NONNULL data() const BOOST_NOEXCEPT_OR_NOTHROW + const CharT* data() const BOOST_NOEXCEPT_OR_NOTHROW { return boost::movelib::to_raw_pointer(this->priv_addr()); } //! Returns: A pointer p such that p + i == &operator[](i) for each i in [0,size()]. //! //! Complexity: constant time. BOOST_CONTAINER_NODISCARD inline - CharT* BOOST_CONTAINER_NONNULL data() BOOST_NOEXCEPT_OR_NOTHROW + CharT* data() BOOST_NOEXCEPT_OR_NOTHROW { return boost::movelib::to_raw_pointer(this->priv_addr()); } #ifndef BOOST_CONTAINER_TEMPLATED_CONVERSION_OPERATOR_BROKEN @@ -2411,8 +2442,9 @@ class basic_string //! //! Returns: find(basic_string(s,n),pos). BOOST_CONTAINER_NODISCARD inline - size_type find(const CharT* BOOST_CONTAINER_NONNULL s, size_type pos, size_type n) const + size_type find(const CharT* s, size_type pos, size_type n) const { + BOOST_ASSERT(s != 0); if (pos + n > this->size()) return npos; else { @@ -2432,8 +2464,11 @@ class basic_string //! //! Returns: find(basic_string(s), pos). BOOST_CONTAINER_NODISCARD inline - size_type find(const CharT* BOOST_CONTAINER_NONNULL s, size_type pos = 0) const - { return this->find(s, pos, Traits::length(s)); } + size_type find(const CharT* s, size_type pos = 0) const + { + BOOST_ASSERT(s != 0); + return this->find(s, pos, Traits::length(s)); + } //! Throws: Nothing //! @@ -2485,8 +2520,9 @@ class basic_string //! //! Returns: rfind(basic_string(s, n), pos). BOOST_CONTAINER_NODISCARD inline - size_type rfind(const CharT* BOOST_CONTAINER_NONNULL s, size_type pos, size_type n) const + size_type rfind(const CharT* s, size_type pos, size_type n) const { + BOOST_ASSERT(s != 0); const size_type len = this->size(); if (n > len) @@ -2508,8 +2544,11 @@ class basic_string //! //! Returns: rfind(basic_string(s), pos). BOOST_CONTAINER_NODISCARD inline - size_type rfind(const CharT* BOOST_CONTAINER_NONNULL s, size_type pos = npos) const - { return this->rfind(s, pos, Traits::length(s)); } + size_type rfind(const CharT* s, size_type pos = npos) const + { + BOOST_ASSERT(s != 0); + return this->rfind(s, pos, Traits::length(s)); + } //! Throws: Nothing //! @@ -2559,8 +2598,9 @@ class basic_string //! //! Returns: find_first_of(basic_string(s, n), pos). BOOST_CONTAINER_NODISCARD inline - size_type find_first_of(const CharT* BOOST_CONTAINER_NONNULL s, size_type pos, size_type n) const + size_type find_first_of(const CharT* s, size_type pos, size_type n) const { + BOOST_ASSERT(s != 0); const size_type sz = this->size(); if (pos >= sz) return npos; @@ -2579,8 +2619,11 @@ class basic_string //! //! Returns: find_first_of(basic_string(s), pos). BOOST_CONTAINER_NODISCARD inline - size_type find_first_of(const CharT* BOOST_CONTAINER_NONNULL s, size_type pos = 0) const - { return this->find_first_of(s, pos, Traits::length(s)); } + size_type find_first_of(const CharT* s, size_type pos = 0) const + { + BOOST_ASSERT(s != 0); + return this->find_first_of(s, pos, Traits::length(s)); + } //! Requires: s points to an array of at least traits::length(s) + 1 elements of CharT. //! @@ -2620,8 +2663,9 @@ class basic_string //! //! Returns: find_last_of(basic_string(s, n), pos). BOOST_CONTAINER_NODISCARD inline - size_type find_last_of(const CharT* BOOST_CONTAINER_NONNULL s, size_type pos, size_type n) const + size_type find_last_of(const CharT* s, size_type pos, size_type n) const { + BOOST_ASSERT(s != 0); const size_type len = this->size(); if (len < 1) @@ -2642,8 +2686,11 @@ class basic_string //! //! Returns: find_last_of(basic_string(1,c),pos). BOOST_CONTAINER_NODISCARD inline - size_type find_last_of(const CharT* BOOST_CONTAINER_NONNULL s, size_type pos = npos) const - { return this->find_last_of(s, pos, Traits::length(s)); } + size_type find_last_of(const CharT* s, size_type pos = npos) const + { + BOOST_ASSERT(s != 0); + return this->find_last_of(s, pos, Traits::length(s)); + } //! Throws: Nothing //! @@ -2683,8 +2730,9 @@ class basic_string //! //! Returns: find_first_not_of(basic_string(s, n), pos). BOOST_CONTAINER_NODISCARD inline - size_type find_first_not_of(const CharT* BOOST_CONTAINER_NONNULL s, size_type pos, size_type n) const + size_type find_first_not_of(const CharT* s, size_type pos, size_type n) const { + BOOST_ASSERT(s != 0); if (pos > this->size()) return npos; else { @@ -2702,8 +2750,11 @@ class basic_string //! //! Returns: find_first_not_of(basic_string(s), pos). BOOST_CONTAINER_NODISCARD inline - size_type find_first_not_of(const CharT* BOOST_CONTAINER_NONNULL s, size_type pos = 0) const - { return this->find_first_not_of(s, pos, Traits::length(s)); } + size_type find_first_not_of(const CharT* s, size_type pos = 0) const + { + BOOST_ASSERT(s != 0); + return this->find_first_not_of(s, pos, Traits::length(s)); + } //! Throws: Nothing //! @@ -2752,8 +2803,9 @@ class basic_string //! //! Returns: find_last_not_of(basic_string(s, n), pos). BOOST_CONTAINER_NODISCARD inline - size_type find_last_not_of(const CharT* BOOST_CONTAINER_NONNULL s, size_type pos, size_type n) const + size_type find_last_not_of(const CharT* s, size_type pos, size_type n) const { + BOOST_ASSERT(s != 0); const size_type len = this->size(); if (len < 1) @@ -2773,8 +2825,11 @@ class basic_string //! //! Returns: find_last_not_of(basic_string(s), pos). BOOST_CONTAINER_NODISCARD inline - size_type find_last_not_of(const CharT* BOOST_CONTAINER_NONNULL s, size_type pos = npos) const - { return this->find_last_not_of(s, pos, Traits::length(s)); } + size_type find_last_not_of(const CharT* s, size_type pos = npos) const + { + BOOST_ASSERT(s != 0); + return this->find_last_not_of(s, pos, Traits::length(s)); + } //! Throws: Nothing //! @@ -2874,7 +2929,7 @@ class basic_string if (pos1 > this->size()) throw_out_of_range("basic_string::compare out of range position"); const pointer addr = this->priv_addr() + pos1; - const CharT* BOOST_CONTAINER_NONNULL str_addr = sv.data(); + const CharT* const str_addr = sv.data(); return this->s_compare(addr, addr + difference_type(dtl::min_value(n1, this->size() - pos1)), str_addr, str_addr + sv.size()); } @@ -2922,9 +2977,10 @@ class basic_string //! //! Returns: compare(basic_string(s)). BOOST_CONTAINER_NODISCARD inline - int compare(const CharT* BOOST_CONTAINER_NONNULL s) const + int compare(const CharT* s) const { - const pointer addr = this->priv_addr(); + BOOST_ASSERT(s != 0); + const_pointer const addr = this->priv_addr(); return this->s_compare(addr, addr + difference_type(this->priv_size()), s, s + Traits::length(s)); } @@ -2934,8 +2990,9 @@ class basic_string //! //! Returns: basic_string(*this, pos, n1).compare(basic_string(s, n2)). BOOST_CONTAINER_NODISCARD inline - int compare(size_type pos1, size_type n1, const CharT* BOOST_CONTAINER_NONNULL s, size_type n2) const + int compare(size_type pos1, size_type n1, const CharT* s, size_type n2) const { + BOOST_ASSERT(s != 0); if (pos1 > this->size()) throw_out_of_range("basic_string::compare out of range position"); const pointer addr = this->priv_addr(); @@ -2950,8 +3007,11 @@ class basic_string //! //! Returns: basic_string(*this, pos, n1).compare(basic_string(s, n2)). BOOST_CONTAINER_NODISCARD inline - int compare(size_type pos1, size_type n1, const CharT* BOOST_CONTAINER_NONNULL s) const - { return this->compare(pos1, n1, s, Traits::length(s)); } + int compare(size_type pos1, size_type n1, const CharT* s) const + { + BOOST_ASSERT(s != 0); + return this->compare(pos1, n1, s, Traits::length(s)); + } //! Effects: Equivalent to find(sv) != npos //! @@ -2978,8 +3038,10 @@ class basic_string //! //! Returns: true if the string contains the provided substring, false otherwise. BOOST_CONTAINER_NODISCARD inline - bool contains(const CharT* BOOST_CONTAINER_NONNULL s) const BOOST_NOEXCEPT - { return this->find(s) != npos; } + bool contains(const CharT* s) const BOOST_NOEXCEPT + { + return this->find(s) != npos; //find checks s != 0 + } //! Effects: Checks if the string begins with the given prefix //! @@ -3010,8 +3072,9 @@ class basic_string //! //! Returns: true if the string begins with the provided prefix, false otherwise. BOOST_CONTAINER_NODISCARD inline - bool starts_with(const CharT* BOOST_CONTAINER_NONNULL s) const BOOST_NOEXCEPT + bool starts_with(const CharT* s) const BOOST_NOEXCEPT { + BOOST_ASSERT(s != 0); const std::size_t s_sz = Traits::length(s); const std::size_t t_sz = this->size(); return t_sz >= s_sz && Traits::compare(this->data(), s, s_sz) == 0; @@ -3046,8 +3109,9 @@ class basic_string //! //! Returns: true if the string begins with the provided suffix, false otherwise. BOOST_CONTAINER_NODISCARD inline - bool ends_with(const CharT* BOOST_CONTAINER_NONNULL s) const BOOST_NOEXCEPT + bool ends_with(const CharT* s) const BOOST_NOEXCEPT { + BOOST_ASSERT(s != 0); const std::size_t s_sz = Traits::length(s); const std::size_t t_sz = this->size(); return t_sz >= s_sz && Traits::compare(this->data() + std::ptrdiff_t(t_sz - s_sz), s, s_sz) == 0; @@ -3125,7 +3189,7 @@ class basic_string template void priv_shrink_to_fit_dynamic_buffer ( AllocVersion - , typename dtl::enable_if >::type* BOOST_CONTAINER_NULLABLE = 0) + , typename dtl::enable_if >::type* = 0) { //Allocate a new buffer. size_type real_cap = 0; @@ -3155,7 +3219,7 @@ class basic_string template void priv_shrink_to_fit_dynamic_buffer ( AllocVersion - , typename dtl::enable_if >::type* BOOST_CONTAINER_NULLABLE = 0) + , typename dtl::enable_if >::type* = 0) { size_type received_size = this->priv_long_size()+1; pointer hint = this->priv_long_addr(); @@ -3192,9 +3256,7 @@ class basic_string Traits::assign(*result, *first); } - static inline void priv_copy( const CharT* BOOST_CONTAINER_NULLABLE first - , const CharT* BOOST_CONTAINER_NULLABLE last - , CharT* BOOST_CONTAINER_NONNULL result) + static inline void priv_copy( const CharT* first, const CharT* last, CharT* result) { Traits::copy(result, first, std::size_t(last - first)); } template @@ -3313,17 +3375,18 @@ template inline template inline basic_string operator+ - (const CharT* BOOST_CONTAINER_NONNULL s, basic_string y) + (const CharT* s, basic_string y) { + BOOST_ASSERT(s != 0); y.insert(y.begin(), s, s + Traits::length(s)); return y; } template inline basic_string operator+ - (basic_string x, const CharT* BOOST_CONTAINER_NONNULL s) + (basic_string x, const CharT* s) { - x += s; + x += s; //operator+= checks s != 0 return x; } @@ -3355,16 +3418,18 @@ operator==(const basic_string& x, const basic_string inline bool -operator==(const CharT* BOOST_CONTAINER_NONNULL s, const basic_string& y) +operator==(const CharT* s, const basic_string& y) { + BOOST_ASSERT(s != 0); typename basic_string::size_type n = Traits::length(s); return n == y.size() && Traits::compare(s, y.data(), n) == 0; } template inline bool -operator==(const basic_string& x, const CharT* BOOST_CONTAINER_NONNULL s) +operator==(const basic_string& x, const CharT* s) { + BOOST_ASSERT(s != 0); typename basic_string::size_type n = Traits::length(s); return x.size() == n && Traits::compare(x.data(), s, n) == 0; } @@ -3398,14 +3463,17 @@ operator!=(const basic_string& x, const basic_string inline bool -operator!=(const CharT* BOOST_CONTAINER_NONNULL s, const basic_string& y) - { return !(s == y); } +operator!=(const CharT* s, const basic_string& y) +{ + return !(s == y); +} template inline bool -operator!=(const basic_string& x, const CharT* BOOST_CONTAINER_NONNULL s) - { return !(x == s); } - +operator!=(const basic_string& x, const CharT* s) +{ + return !(x == s); +} template class BasicStringView> inline @@ -3433,14 +3501,14 @@ operator<(const basic_string& x, const basic_string inline bool -operator<(const CharT* BOOST_CONTAINER_NONNULL s, const basic_string& y) +operator<(const CharT* s, const basic_string& y) { return y.compare(s) > 0; } template inline bool -operator<(const basic_string& x, const CharT* BOOST_CONTAINER_NONNULL s) +operator<(const basic_string& x, const CharT* s) { return x.compare(s) < 0; } @@ -3463,22 +3531,18 @@ operator<( const basic_string& x, BasicStringView inline bool -operator>(const basic_string& x, const basic_string& y) { - return y < x; -} +operator>(const basic_string& x, const basic_string& y) +{ return y < x; } template inline bool -operator>(const CharT* BOOST_CONTAINER_NONNULL s, const basic_string& y) { - return y < s; -} +operator>(const CharT* s, const basic_string& y) +{ return y < s; } template inline bool -operator>(const basic_string& x, const CharT* BOOST_CONTAINER_NONNULL s) -{ - return s < x; -} +operator>(const basic_string& x, const CharT* s) +{ return s < x; } template class BasicStringView> inline @@ -3505,12 +3569,12 @@ operator<=(const basic_string& x, const basic_string inline bool -operator<=(const CharT* BOOST_CONTAINER_NONNULL s, const basic_string& y) +operator<=(const CharT* s, const basic_string& y) { return !(y < s); } template inline bool -operator<=(const basic_string& x, const CharT* BOOST_CONTAINER_NONNULL s) +operator<=(const basic_string& x, const CharT* s) { return !(s < x); } @@ -3538,12 +3602,12 @@ operator>=(const basic_string& x, template inline bool -operator>=(const CharT* BOOST_CONTAINER_NONNULL s, const basic_string& y) +operator>=(const CharT* s, const basic_string& y) { return !(s < y); } template inline bool -operator>=(const basic_string& x, const CharT* BOOST_CONTAINER_NONNULL s) +operator>=(const basic_string& x, const CharT* s) { return !(x < s); } template class BasicStringView> @@ -3575,7 +3639,7 @@ namespace dtl { template inline bool string_fill(std::basic_ostream& os, - std::basic_streambuf* BOOST_CONTAINER_NONNULL buf, + std::basic_streambuf* buf, std::size_t n) { CharT f = os.fill(); diff --git a/test/string_test.cpp b/test/string_test.cpp index 1030e66..147f00a 100644 --- a/test/string_test.cpp +++ b/test/string_test.cpp @@ -1291,6 +1291,9 @@ void test_insert_initializer_list() s.insert(s.end(), {'d', 'e', 'f'}); BOOST_TEST(s == "abcdef"); + + s.insert(s.end(), {}); + BOOST_TEST(s == "abcdef"); #endif } @@ -1412,6 +1415,9 @@ void test_append_initializer_list() s.append({',', ' ', 'W', 'o', 'r', 'l', 'd', '!'}); BOOST_TEST(s == "Hello, World!"); + + s.append({}); + BOOST_TEST(s == "Hello, World!"); #endif } @@ -1435,6 +1441,8 @@ void test_operator_plus_equals() // += initializer_list s += {'!', '!'}; BOOST_TEST(s == "Hello, World!!!"); + s += {}; + BOOST_TEST(s == "Hello, World!!!"); #endif } @@ -1587,6 +1595,8 @@ void test_replace_iterator() s = "Hello, World!"; s.replace(s.begin() + 7, s.begin() + 12, {'S', 'u', 'n'}); BOOST_TEST(s == "Hello, Sun!"); + s.replace(s.begin() + 5, s.begin() + 10, {}); + BOOST_TEST(s == "Hello!"); #endif }