From 95924b1329da49e70c9c8485b87e066895db2d64 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 4 Oct 2021 16:49:46 +0300 Subject: [PATCH 001/258] Add boost/core/string_view.hpp --- doc/string_view.qbk | 181 +++++++++ include/boost/core/string_view.hpp | 567 +++++++++++++++++++++++++++++ test/Jamfile.v2 | 2 + test/sv_types_test.cpp | 49 +++ 4 files changed, 799 insertions(+) create mode 100644 doc/string_view.qbk create mode 100644 include/boost/core/string_view.hpp create mode 100644 test/sv_types_test.cpp diff --git a/doc/string_view.qbk b/doc/string_view.qbk new file mode 100644 index 0000000..e92c295 --- /dev/null +++ b/doc/string_view.qbk @@ -0,0 +1,181 @@ +[/ + Copyright 2021 Peter Dimov + Distributed under the Boost Software License, Version 1.0. + https://boost.org/LICENSE_1_0.txt +] + +[section:string_view string_view] + +[simplesect Authors] + +* Peter Dimov + +[endsimplesect] + +[section Header ] + +The header `` defines `boost::core::string_view`, +a portable and interoperable implementation of `std::string_view`. + +Unlike `boost::string_view`, `boost::core::string_view` has implicit +conversions from and to `std::string_view`, which allows Boost libraries that +support C++11/C++14 to use it in interfaces without forcing users to forgo the +use of `std::string_view` in their code. + +[section Synopsis] + +`` +namespace boost +{ +namespace core +{ + +template class basic_string_view +{ +private: + + Ch const* data_; + std::size_t size_; + +public: + + // types + + typedef std::char_traits traits_type; + typedef Ch value_type; + typedef Ch* pointer; + typedef Ch const* const_pointer; + typedef Ch& reference; + typedef Ch const& const_reference; + typedef Ch const* const_iterator; + typedef const_iterator iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef const_reverse_iterator reverse_iterator; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + // npos + + static constexpr size_type npos = static_cast( -1 ); + +public: + + // construction and assignment + + constexpr basic_string_view() noexcept; + constexpr basic_string_view( basic_string_view const& ) noexcept = default; + constexpr basic_string_view& operator=( basic_string_view const& ) noexcept & = default; + constexpr basic_string_view( Ch const* str ) noexcept; + constexpr basic_string_view( Ch const* str, size_type len ) noexcept; + constexpr basic_string_view( Ch const* begin, Ch const* end ) noexcept; + template basic_string_view(std::basic_string, A> const& str ) noexcept; + basic_string_view(std::basic_string_view> const& str ) noexcept; + + // iterator support + + constexpr const_iterator begin() const noexcept; + constexpr const_iterator end() const noexcept; + constexpr const_iterator cbegin() const noexcept; + constexpr const_iterator cend() const noexcept; + constexpr const_reverse_iterator rbegin() const noexcept; + constexpr const_reverse_iterator rend() const noexcept; + constexpr const_reverse_iterator crbegin() const noexcept; + constexpr const_reverse_iterator crend() const noexcept; + + // capacity + + constexpr size_type size() const noexcept; + constexpr size_type length() const noexcept; + constexpr size_type max_size() const noexcept; + constexpr bool empty() const noexcept; + + // element access + + constexpr const_reference operator[]( size_type pos ) const noexcept; + constexpr const_reference at( size_type pos ) const; + constexpr const_reference front() const noexcept; + constexpr const_reference back() const noexcept; + constexpr const_pointer data() const noexcept; + + // modifiers + + constexpr void remove_prefix( size_type n ) noexcept; + constexpr void remove_suffix( size_type n ) noexcept; + constexpr void swap( basic_string_view& s ) noexcept; + + // string operations + + constexpr size_type copy( Ch* s, size_type n, size_type pos = 0 ) const; + constexpr basic_string_view substr( size_type pos = 0, size_type n = npos ) const; + + constexpr int compare( basic_string_view s ) const noexcept; + constexpr int compare( size_type pos1, size_type n1, basic_string_view s ) const; + constexpr int compare( size_type pos1, size_type n1, basic_string_view s, size_type pos2, size_type n2 ) const; + constexpr int compare( Ch const* s ) const; + constexpr int compare( size_type pos1, size_type n1, Ch const* s ) const; + constexpr int compare( size_type pos1, size_type n1, Ch const* s, size_type n2 ) const; + + constexpr bool starts_with( basic_string_view x ) const noexcept; + constexpr bool starts_with( Ch x ) const noexcept; + constexpr bool starts_with( Ch const* x ) const; + + constexpr bool ends_with( basic_string_view x ) const noexcept; + constexpr bool ends_with( Ch x ) const noexcept; constexpr bool ends_with( Ch const* x ) const; + + // searching + + constexpr size_type find( basic_string_view s, size_type pos = 0 ) const noexcept; + constexpr size_type find( Ch c, size_type pos = 0 ) const noexcept; + constexpr size_type find( Ch const* s, size_type pos, size_type n ) const; + constexpr size_type find( Ch const* s, size_type pos = 0 ) const; + + constexpr size_type rfind( basic_string_view s, size_type pos = npos ) const noexcept; + constexpr size_type rfind( Ch c, size_type pos = npos ) const noexcept; + constexpr size_type rfind( Ch const* s, size_type pos, size_type n ) const; + constexpr size_type rfind( Ch const* s, size_type pos = npos ) const; + + constexpr size_type find_first_of( basic_string_view s, size_type pos = 0 ) const noexcept; + constexpr size_type find_first_of( Ch c, size_type pos = 0 ) const noexcept; + constexpr size_type find_first_of( Ch const* s, size_type pos, size_type n ) const; + constexpr size_type find_first_of( Ch const* s, size_type pos = 0 ) const; + + constexpr size_type find_last_of( basic_string_view s, size_type pos = npos ) const noexcept; + constexpr size_type find_last_of( Ch c, size_type pos = npos ) const noexcept; + constexpr size_type find_last_of( Ch const* s, size_type pos, size_type n ) const; + constexpr size_type find_last_of( Ch const* s, size_type pos = npos ) const; + + constexpr size_type find_first_not_of( basic_string_view s, size_type pos = 0 ) const noexcept; + constexpr size_type find_first_not_of( Ch c, size_type pos = 0 ) const noexcept; + constexpr size_type find_first_not_of( Ch const* s, size_type pos, size_type n ) const; + constexpr size_type find_first_not_of( Ch const* s, size_type pos = 0 ) const; + + constexpr size_type find_last_not_of( basic_string_view s, size_type pos = npos ) const noexcept; + constexpr size_type find_last_not_of( Ch c, size_type pos = npos ) const noexcept; + constexpr size_type find_last_not_of( Ch const* s, size_type pos, size_type n ) const; + constexpr size_type find_last_not_of( Ch const* s, size_type pos = npos ) const; }; + +typedef basic_string_view string_view; +typedef basic_string_view wstring_view; +typedef basic_string_view u16string_view; +typedef basic_string_view u32string_view; +typedef basic_string_view u8string_view; + +} // namespace core +} // namespace boost +`` + +[endsect] + +[section Construction] + +[section constexpr basic_string_view() noexcept;] + +* *Ensures:* `data() == 0`, `size() == 0`. + +[endsect] + +[endsect] + +[endsect] + +[endsect] diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp new file mode 100644 index 0000000..9fcdd84 --- /dev/null +++ b/include/boost/core/string_view.hpp @@ -0,0 +1,567 @@ +#ifndef BOOST_CORE_STRING_VIEW_HPP_INCLUDED +#define BOOST_CORE_STRING_VIEW_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// boost::core::basic_string_view +// +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) +# include +#endif + +namespace boost +{ +namespace core +{ + +template class basic_string_view +{ +private: + + Ch const* p_; + std::size_t n_; + +public: + + // types + + typedef std::char_traits traits_type; + typedef Ch value_type; + typedef Ch* pointer; + typedef Ch const* const_pointer; + typedef Ch& reference; + typedef Ch const& const_reference; + typedef Ch const* const_iterator; + typedef const_iterator iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef const_reverse_iterator reverse_iterator; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + // npos + + BOOST_STATIC_CONSTEXPR size_type npos = static_cast( -1 ); + +public: + + // construction and assignment + + BOOST_CONSTEXPR basic_string_view() BOOST_NOEXCEPT: p_(), n_() + { + } + + BOOST_CONSTEXPR basic_string_view( Ch const* str ) BOOST_NOEXCEPT: p_( str ), n_( traits_type::length( str ) ) + { + } + + BOOST_CONSTEXPR basic_string_view( Ch const* str, size_type len ) BOOST_NOEXCEPT: p_( str ), n_( len ) + { + } + + BOOST_CXX14_CONSTEXPR basic_string_view( Ch const* begin, Ch const* end ) BOOST_NOEXCEPT: p_( begin ), n_( end - begin ) + { + BOOST_ASSERT( end - begin >= 0 ); + } + + template basic_string_view( std::basic_string, A> const& str ) BOOST_NOEXCEPT: p_( str.data() ), n_( str.size() ) + { + } + +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) + + basic_string_view( std::basic_string_view > const& str ) BOOST_NOEXCEPT: p_( str.data() ), n_( str.size() ) + { + } + +#endif + + // BOOST_CONSTEXPR basic_string_view& operator=( basic_string_view const& ) BOOST_NOEXCEPT & = default; + + // iterator support + + BOOST_CONSTEXPR const_iterator begin() const BOOST_NOEXCEPT + { + return p_; + } + + BOOST_CONSTEXPR const_iterator end() const BOOST_NOEXCEPT + { + return p_ + n_; + } + + BOOST_CONSTEXPR const_iterator cbegin() const BOOST_NOEXCEPT + { + return p_; + } + + BOOST_CONSTEXPR const_iterator cend() const BOOST_NOEXCEPT + { + return p_ + n_; + } + + BOOST_CONSTEXPR const_reverse_iterator rbegin() const BOOST_NOEXCEPT + { + return const_reverse_iterator( begin() ); + } + + BOOST_CONSTEXPR const_reverse_iterator rend() const BOOST_NOEXCEPT + { + return const_reverse_iterator( end() ); + } + + BOOST_CONSTEXPR const_reverse_iterator crbegin() const BOOST_NOEXCEPT + { + return const_reverse_iterator( begin() ); + } + + BOOST_CONSTEXPR const_reverse_iterator crend() const BOOST_NOEXCEPT + { + return const_reverse_iterator( end() ); + } + + // capacity + + BOOST_CONSTEXPR size_type size() const BOOST_NOEXCEPT + { + return n_; + } + + BOOST_CONSTEXPR size_type length() const BOOST_NOEXCEPT + { + return n_; + } + + BOOST_CONSTEXPR size_type max_size() const BOOST_NOEXCEPT + { + return npos / sizeof( Ch ); + } + + BOOST_CONSTEXPR bool empty() const BOOST_NOEXCEPT + { + return n_ == 0; + } + + // element access + + BOOST_CONSTEXPR const_reference operator[]( size_type pos ) const BOOST_NOEXCEPT + { + BOOST_ASSERT( pos < size() ); + return p_[ pos ]; + } + + BOOST_CONSTEXPR const_reference at( size_type pos ) const + { + if( pos >= size() ) + { + boost::throw_exception( std::out_of_range( "basic_string_view::at" ), BOOST_CURRENT_LOCATION ); + } + + return p_[ pos ]; + } + + BOOST_CONSTEXPR const_reference front() const BOOST_NOEXCEPT + { + BOOST_ASSERT( !empty() ); + return p_[ 0 ]; + } + + BOOST_CONSTEXPR const_reference back() const BOOST_NOEXCEPT + { + BOOST_ASSERT( !empty() ); + return p_[ n_ - 1 ]; + } + + BOOST_CONSTEXPR const_pointer data() const BOOST_NOEXCEPT + { + return p_; + } + + // modifiers + + BOOST_CXX14_CONSTEXPR void remove_prefix( size_type n ) BOOST_NOEXCEPT + { + BOOST_ASSERT( n <= size() ); + + p_ += n; + n_ -= n; + } + + BOOST_CXX14_CONSTEXPR void remove_suffix( size_type n ) BOOST_NOEXCEPT + { + BOOST_ASSERT( n <= size() ); + + n_ -= n; + } + + BOOST_CXX14_CONSTEXPR void swap( basic_string_view& s ) BOOST_NOEXCEPT + { + std::swap( p_, s.p_ ); + std::swap( n_, s.n_ ); + } + + // string operations + + BOOST_CONSTEXPR size_type copy( Ch* s, size_type n, size_type pos = 0 ) const + { + if( pos > size() ) + { + boost::throw_exception( std::out_of_range( "basic_string_view::copy" ), BOOST_CURRENT_LOCATION ); + } + + std::size_t rlen = std::min( n, size() - pos ); + + traits_type::copy( s, data() + pos, rlen ); + + return rlen; + } + + BOOST_CONSTEXPR basic_string_view substr( size_type pos = 0, size_type n = npos ) const + { + if( pos > size() ) + { + boost::throw_exception( std::out_of_range( "basic_string_view::substr" ), BOOST_CURRENT_LOCATION ); + } + + std::size_t rlen = std::min( n, size() - pos ); + + return basic_string_view( data() + pos, rlen ); + } + + // compare + + BOOST_CONSTEXPR int compare( basic_string_view str ) const BOOST_NOEXCEPT + { + std::size_t rlen = std::min( size(), str.size() ); + + int cmp = traits_type::compare( data(), str.data(), rlen ); + + if( cmp != 0 ) return cmp; + + if( size() == str.size() ) return 0; + + return size() < str.size()? -1: +1; + } + + BOOST_CONSTEXPR int compare( size_type pos1, size_type n1, basic_string_view str ) const + { + return substr( pos1, n1 ).compare( str ); + } + + BOOST_CONSTEXPR int compare( size_type pos1, size_type n1, basic_string_view str, size_type pos2, size_type n2 ) const + { + return substr( pos1, n1 ).compare( str.substr( pos2, n2 ) ); } + + BOOST_CONSTEXPR int compare( Ch const* s ) const BOOST_NOEXCEPT + { + return compare( basic_string_view( s ) ); } + + BOOST_CONSTEXPR int compare( size_type pos1, size_type n1, Ch const* s ) const + { + return substr( pos1, n1 ).compare( basic_string_view( s ) ); + } + + BOOST_CONSTEXPR int compare( size_type pos1, size_type n1, Ch const* s, size_type n2 ) const + { + return substr( pos1, n1 ).compare( basic_string_view( s, n2 ) ); } + + // starts_with + + BOOST_CONSTEXPR bool starts_with( basic_string_view x ) const BOOST_NOEXCEPT + { + return substr( 0, x.size() ) == x; + } + + BOOST_CONSTEXPR bool starts_with( Ch x ) const BOOST_NOEXCEPT + { + return !empty() && front() == x; } + + BOOST_CONSTEXPR bool starts_with( Ch const* x ) const + { + return starts_with( basic_string_view( x ) ); + } + + // ends_with + + BOOST_CONSTEXPR bool ends_with( basic_string_view x ) const BOOST_NOEXCEPT + { + return size() >= x.size() && compare( size() - x.size(), npos, x ) == 0; } + + BOOST_CONSTEXPR bool ends_with( Ch x ) const BOOST_NOEXCEPT { return !empty() && back() == x; } BOOST_CONSTEXPR bool ends_with( Ch const* x ) const + { + return ends_with( basic_string_view( x ) ); + } + + // find + + BOOST_CONSTEXPR size_type find( basic_string_view str, size_type pos = 0 ) const BOOST_NOEXCEPT + { + return find( str.data(), pos, str.size() ); + } + + BOOST_CONSTEXPR size_type find( Ch c, size_type pos = 0 ) const BOOST_NOEXCEPT + { + if( pos >= size() ) return npos; + + Ch const* r = traits_type::find( data() + pos, size() - pos, c ); + + return r? r - data(): npos; + } + + BOOST_CONSTEXPR size_type find( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT + { + if( pos + n > size() ) return npos; + if( n == 0 ) return pos; + + Ch const* p = data() + pos; + Ch const* last = data() + size(); + + for( ;; ) + { + p = traits_type::find( p, last - p, s[0] ); + + if( p == 0 ) break; + if( last - p < n ) break; + + if( traits_type::compare( p, s, n ) == 0 ) return p - data(); + + ++p; + } + + return npos; + } + + BOOST_CONSTEXPR size_type find( Ch const* s, size_type pos = 0 ) const BOOST_NOEXCEPT + { + return find( s, pos, traits_type::length( s ) ); + } + + // rfind + + BOOST_CONSTEXPR size_type rfind( basic_string_view str, size_type pos = npos ) const BOOST_NOEXCEPT + { + return rfind( str.data(), pos, str.size() ); + } + + BOOST_CONSTEXPR size_type rfind( Ch c, size_type pos = npos ) const BOOST_NOEXCEPT + { + if( pos > size() ) + { + pos = size(); + } + + const_reverse_iterator r = std::find( rbegin() + pos, rend(), c ); + return r == rend()? npos: size() - 1 - ( r - rbegin() ); + } + + BOOST_CONSTEXPR size_type rfind( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT + { + if( n > size() ) return npos; + + if( pos > size() - n ) + { + pos = size() - n; + } + + if( n == 0 ) return pos; + + for( ;; ) + { + size_type xpos = rfind( s[0], pos ); + + if( xpos == npos ) return npos; + + if( traits_type::compare( data() + xpos, s, n ) == 0 ) return xpos; + + if( xpos == 0 ) return npos; + + pos = xpos - 1; + } + } + + BOOST_CONSTEXPR size_type rfind( Ch const* s, size_type pos = npos ) const BOOST_NOEXCEPT + { + return rfind( s, pos, traits_type::length( s ) ); + } + + // find_first_of + + BOOST_CONSTEXPR size_type find_first_of( basic_string_view str, size_type pos = 0 ) const BOOST_NOEXCEPT + { + for( std::size_t i = pos; i < n_; ++i ) + { + if( str.contains( p_[ i ] ) ) return i; + } + + return npos; + } + + BOOST_CONSTEXPR size_type find_first_of( Ch c, size_type pos = 0 ) const BOOST_NOEXCEPT + { + return find( c, pos ); + } + + BOOST_CONSTEXPR size_type find_first_of( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT + { + return find_first_of( basic_string_view( s, n ), pos ); + } + + BOOST_CONSTEXPR size_type find_first_of( Ch const* s, size_type pos = 0 ) const BOOST_NOEXCEPT + { + return find_first_of( basic_string_view( s ), pos ); + } + + // find_last_of + + BOOST_CONSTEXPR size_type find_last_of( basic_string_view str, size_type pos = npos ) const BOOST_NOEXCEPT + { + if( pos > size() ) + { + pos = size(); + } + + for( std::size_t i = pos; i > 0; --i ) + { + if( str.contains( p_[ i - 1 ] ) ) return i - 1; + } + + return npos; + } + + BOOST_CONSTEXPR size_type find_last_of( Ch c, size_type pos = npos ) const BOOST_NOEXCEPT + { + return rfind( c, pos ); + } + + BOOST_CONSTEXPR size_type find_last_of( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT + { + return find_last_of( basic_string_view( s, n ), pos ); + } + + BOOST_CONSTEXPR size_type find_last_of( Ch const* s, size_type pos = npos ) const BOOST_NOEXCEPT + { + return find_last_of( basic_string_view( s ), pos ); + } + + // find_first_not_of + + BOOST_CONSTEXPR size_type find_first_not_of( basic_string_view str, size_type pos = 0 ) const BOOST_NOEXCEPT + { + for( std::size_t i = pos; i < n_; ++i ) + { + if( !str.contains( p_[ i ] ) ) return i; + } + + return npos; + } + + BOOST_CONSTEXPR size_type find_first_not_of( Ch c, size_type pos = 0 ) const BOOST_NOEXCEPT + { + for( std::size_t i = pos; i < n_; ++i ) + { + if( p_[ i ] != c ) return i; + } + + return npos; + } + + BOOST_CONSTEXPR size_type find_first_not_of( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT + { + return find_first_not_of( basic_string_view( s, n ), pos ); + } + + BOOST_CONSTEXPR size_type find_first_not_of( Ch const* s, size_type pos = 0 ) const BOOST_NOEXCEPT + { + return find_first_not_of( basic_string_view( s ), pos ); + } + + // find_last_not_of + + BOOST_CONSTEXPR size_type find_last_not_of( basic_string_view str, size_type pos = npos ) const BOOST_NOEXCEPT + { + if( pos > size() ) + { + pos = size(); + } + + for( std::size_t i = pos; i > 0; --i ) + { + if( !str.contains( p_[ i - 1 ] ) ) return i - 1; + } + + return npos; + } + + BOOST_CONSTEXPR size_type find_last_not_of( Ch c, size_type pos = npos ) const BOOST_NOEXCEPT + { + if( pos > size() ) + { + pos = size(); + } + + for( std::size_t i = pos; i > 0; --i ) + { + if( p_[ i - 1 ] != c ) return i - 1; + } + + return npos; + } + + BOOST_CONSTEXPR size_type find_last_not_of( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT + { + return find_last_not_of( basic_string_view( s, n ), pos ); } + BOOST_CONSTEXPR size_type find_last_not_of( Ch const* s, size_type pos = npos ) const BOOST_NOEXCEPT { return find_last_not_of( basic_string_view( s ), pos ); } // contains BOOST_CONSTEXPR bool contains( basic_string_view sv ) const BOOST_NOEXCEPT + { + return find( sv ) != npos; + } + + BOOST_CONSTEXPR bool contains( Ch c ) const BOOST_NOEXCEPT + { + return traits_type::find( data(), size(), c ) == 0; + } + + BOOST_CONSTEXPR bool contains( Ch const* s ) const BOOST_NOEXCEPT + { + return find( s ) != npos; + } +}; + +#if defined(BOOST_NO_CXX17_INLINE_VARIABLES) +template std::size_t const basic_string_view::npos; +#endif + +typedef basic_string_view string_view; +typedef basic_string_view wstring_view; + +#if !defined(BOOST_NO_CXX11_CHAR16_T) +typedef basic_string_view u16string_view; +#endif + +#if !defined(BOOST_NO_CXX11_CHAR32_T) +typedef basic_string_view u32string_view; +#endif + +#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L +typedef basic_string_view u8string_view; +#endif + +} // namespace core +} // namespace boost + +#endif // #ifndef BOOST_CORE_STRING_VIEW_HPP_INCLUDED diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 63f516f..0898060 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -247,5 +247,7 @@ run bit_endian_test.cpp ; run type_name_test.cpp ; +run sv_types_test.cpp ; + use-project /boost/core/swap : ./swap ; build-project ./swap ; diff --git a/test/sv_types_test.cpp b/test/sv_types_test.cpp new file mode 100644 index 0000000..184a49f --- /dev/null +++ b/test/sv_types_test.cpp @@ -0,0 +1,49 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include + +struct Ch +{ +}; + +int main() +{ + using boost::core::is_same; + + typedef boost::core::basic_string_view ch_string_view; + + BOOST_TEST_TRAIT_TRUE((is_same< ch_string_view::traits_type, std::char_traits >)); + BOOST_TEST_TRAIT_TRUE((is_same< ch_string_view::value_type, Ch >)); + BOOST_TEST_TRAIT_TRUE((is_same< ch_string_view::pointer, Ch* >)); + BOOST_TEST_TRAIT_TRUE((is_same< ch_string_view::const_pointer, Ch const* >)); + BOOST_TEST_TRAIT_TRUE((is_same< ch_string_view::reference, Ch& >)); + BOOST_TEST_TRAIT_TRUE((is_same< ch_string_view::const_reference, Ch const& >)); + BOOST_TEST_TRAIT_TRUE((is_same< ch_string_view::iterator, ch_string_view::const_iterator >)); + BOOST_TEST_TRAIT_TRUE((is_same< std::iterator_traits::iterator_category, std::random_access_iterator_tag >)); + BOOST_TEST_TRAIT_TRUE((is_same< ch_string_view::reverse_iterator, ch_string_view::const_reverse_iterator >)); + BOOST_TEST_TRAIT_TRUE((is_same< ch_string_view::reverse_iterator, std::reverse_iterator >)); + BOOST_TEST_TRAIT_TRUE((is_same< ch_string_view::size_type, std::size_t >)); + BOOST_TEST_TRAIT_TRUE((is_same< ch_string_view::difference_type, std::ptrdiff_t >)); + + BOOST_TEST_EQ(ch_string_view::npos, static_cast(-1)); + + BOOST_TEST_TRAIT_TRUE((is_same< boost::core::string_view, boost::core::basic_string_view >)); + BOOST_TEST_TRAIT_TRUE((is_same< boost::core::wstring_view, boost::core::basic_string_view >)); +#if !defined(BOOST_NO_CXX11_CHAR16_T) + BOOST_TEST_TRAIT_TRUE((is_same< boost::core::u16string_view, boost::core::basic_string_view >)); +#endif +#if !defined(BOOST_NO_CXX11_CHAR32_T) + BOOST_TEST_TRAIT_TRUE((is_same< boost::core::u32string_view, boost::core::basic_string_view >)); +#endif +#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L + BOOST_TEST_TRAIT_TRUE((is_same< boost::core::u8string_view, boost::core::basic_string_view >)); +#endif + + return boost::report_errors(); +} From 7d05dfa87df4e3a383f9c07b24511b9ad1d00e61 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 4 Oct 2021 17:25:34 +0300 Subject: [PATCH 002/258] Add sv_construct_test --- include/boost/core/string_view.hpp | 16 +- test/Jamfile.v2 | 1 + test/sv_construct_test.cpp | 305 +++++++++++++++++++++++++++++ 3 files changed, 316 insertions(+), 6 deletions(-) create mode 100644 test/sv_construct_test.cpp diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index 9fcdd84..7857fe1 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -13,7 +13,10 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt +#include +#include #include +#include #include #include #include @@ -75,7 +78,8 @@ public: { } - BOOST_CXX14_CONSTEXPR basic_string_view( Ch const* begin, Ch const* end ) BOOST_NOEXCEPT: p_( begin ), n_( end - begin ) + template BOOST_CXX14_CONSTEXPR basic_string_view( Ch const* begin, End end, + typename boost::enable_if >::type* = 0 ) BOOST_NOEXCEPT: p_( begin ), n_( end - begin ) { BOOST_ASSERT( end - begin >= 0 ); } @@ -160,13 +164,13 @@ public: // element access - BOOST_CONSTEXPR const_reference operator[]( size_type pos ) const BOOST_NOEXCEPT + BOOST_CXX14_CONSTEXPR const_reference operator[]( size_type pos ) const BOOST_NOEXCEPT { BOOST_ASSERT( pos < size() ); return p_[ pos ]; } - BOOST_CONSTEXPR const_reference at( size_type pos ) const + BOOST_CXX14_CONSTEXPR const_reference at( size_type pos ) const { if( pos >= size() ) { @@ -176,13 +180,13 @@ public: return p_[ pos ]; } - BOOST_CONSTEXPR const_reference front() const BOOST_NOEXCEPT + BOOST_CXX14_CONSTEXPR const_reference front() const BOOST_NOEXCEPT { BOOST_ASSERT( !empty() ); return p_[ 0 ]; } - BOOST_CONSTEXPR const_reference back() const BOOST_NOEXCEPT + BOOST_CXX14_CONSTEXPR const_reference back() const BOOST_NOEXCEPT { BOOST_ASSERT( !empty() ); return p_[ n_ - 1 ]; @@ -516,7 +520,7 @@ public: } for( std::size_t i = pos; i > 0; --i ) - { + { if( p_[ i - 1 ] != c ) return i - 1; } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 0898060..1ed8fad 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -248,6 +248,7 @@ run bit_endian_test.cpp ; run type_name_test.cpp ; run sv_types_test.cpp ; +run sv_construct_test.cpp ; use-project /boost/core/swap : ./swap ; build-project ./swap ; diff --git a/test/sv_construct_test.cpp b/test/sv_construct_test.cpp new file mode 100644 index 0000000..af38943 --- /dev/null +++ b/test/sv_construct_test.cpp @@ -0,0 +1,305 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) +# include +#endif + +template std::reverse_iterator make_reverse_iterator( It it ) +{ + return std::reverse_iterator( it ); +} + +int main() +{ + { + boost::core::string_view sv; + + BOOST_TEST_EQ( sv.data(), static_cast(0) ); + BOOST_TEST_EQ( sv.size(), 0 ); + + BOOST_TEST_EQ( sv.begin(), sv.data() ); + BOOST_TEST_EQ( sv.end(), sv.data() + sv.size() ); + + BOOST_TEST_EQ( sv.cbegin(), sv.data() ); + BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); + + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.begin() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.end() ) ); + + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cbegin() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cend() ) ); + + BOOST_TEST_EQ( sv.length(), sv.size() ); + BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); + + BOOST_TEST_EQ( sv.max_size(), boost::core::string_view::npos ); + } + + { + char const* s = ""; + + boost::core::string_view sv( s ); + + BOOST_TEST_EQ( sv.data(), s ); + BOOST_TEST_EQ( sv.size(), 0 ); + + BOOST_TEST_EQ( sv.begin(), sv.data() ); + BOOST_TEST_EQ( sv.end(), sv.data() + sv.size() ); + + BOOST_TEST_EQ( sv.cbegin(), sv.data() ); + BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); + + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.begin() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.end() ) ); + + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cbegin() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cend() ) ); + + BOOST_TEST_EQ( sv.length(), sv.size() ); + BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); + + BOOST_TEST_EQ( sv.max_size(), boost::core::string_view::npos ); + + if( !sv.empty() ) + { + BOOST_TEST_EQ( &sv.front(), sv.data() ); + BOOST_TEST_EQ( &sv.back(), sv.data() + sv.size() - 1 ); + } + } + + { + char const* s = "123"; + + boost::core::string_view sv( s ); + + BOOST_TEST_EQ( sv.data(), s ); + BOOST_TEST_EQ( sv.size(), 3 ); + + BOOST_TEST_EQ( sv.begin(), sv.data() ); + BOOST_TEST_EQ( sv.end(), sv.data() + sv.size() ); + + BOOST_TEST_EQ( sv.cbegin(), sv.data() ); + BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); + + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.begin() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.end() ) ); + + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cbegin() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cend() ) ); + + BOOST_TEST_EQ( sv.length(), sv.size() ); + BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); + + BOOST_TEST_EQ( sv.max_size(), boost::core::string_view::npos ); + + if( !sv.empty() ) + { + BOOST_TEST_EQ( &sv.front(), sv.data() ); + BOOST_TEST_EQ( &sv.back(), sv.data() + sv.size() - 1 ); + } + } + + { + char const* s = "123"; + + boost::core::string_view sv( s, 0 ); + + BOOST_TEST_EQ( sv.data(), s ); + BOOST_TEST_EQ( sv.size(), 0 ); + + BOOST_TEST_EQ( sv.begin(), sv.data() ); + BOOST_TEST_EQ( sv.end(), sv.data() + sv.size() ); + + BOOST_TEST_EQ( sv.cbegin(), sv.data() ); + BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); + + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.begin() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.end() ) ); + + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cbegin() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cend() ) ); + + BOOST_TEST_EQ( sv.length(), sv.size() ); + BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); + + BOOST_TEST_EQ( sv.max_size(), boost::core::string_view::npos ); + + if( !sv.empty() ) + { + BOOST_TEST_EQ( &sv.front(), sv.data() ); + BOOST_TEST_EQ( &sv.back(), sv.data() + sv.size() - 1 ); + } + } + + { + char const* s = "123"; + + boost::core::string_view sv( s, 2 ); + + BOOST_TEST_EQ( sv.data(), s ); + BOOST_TEST_EQ( sv.size(), 2 ); + + BOOST_TEST_EQ( sv.begin(), sv.data() ); + BOOST_TEST_EQ( sv.end(), sv.data() + sv.size() ); + + BOOST_TEST_EQ( sv.cbegin(), sv.data() ); + BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); + + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.begin() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.end() ) ); + + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cbegin() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cend() ) ); + + BOOST_TEST_EQ( sv.length(), sv.size() ); + BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); + + BOOST_TEST_EQ( sv.max_size(), boost::core::string_view::npos ); + + if( !sv.empty() ) + { + BOOST_TEST_EQ( &sv.front(), sv.data() ); + BOOST_TEST_EQ( &sv.back(), sv.data() + sv.size() - 1 ); + } + } + + { + char const* s = "123"; + + boost::core::string_view sv( s, s ); + + BOOST_TEST_EQ( sv.data(), s ); + BOOST_TEST_EQ( sv.size(), 0 ); + + BOOST_TEST_EQ( sv.begin(), sv.data() ); + BOOST_TEST_EQ( sv.end(), sv.data() + sv.size() ); + + BOOST_TEST_EQ( sv.cbegin(), sv.data() ); + BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); + + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.begin() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.end() ) ); + + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cbegin() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cend() ) ); + + BOOST_TEST_EQ( sv.length(), sv.size() ); + BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); + + BOOST_TEST_EQ( sv.max_size(), boost::core::string_view::npos ); + + if( !sv.empty() ) + { + BOOST_TEST_EQ( &sv.front(), sv.data() ); + BOOST_TEST_EQ( &sv.back(), sv.data() + sv.size() - 1 ); + } + } + + { + char const* s = "123"; + + boost::core::string_view sv( s, s + 2 ); + + BOOST_TEST_EQ( sv.data(), s ); + BOOST_TEST_EQ( sv.size(), 2 ); + + BOOST_TEST_EQ( sv.begin(), sv.data() ); + BOOST_TEST_EQ( sv.end(), sv.data() + sv.size() ); + + BOOST_TEST_EQ( sv.cbegin(), sv.data() ); + BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); + + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.begin() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.end() ) ); + + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cbegin() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cend() ) ); + + BOOST_TEST_EQ( sv.length(), sv.size() ); + BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); + + BOOST_TEST_EQ( sv.max_size(), boost::core::string_view::npos ); + + if( !sv.empty() ) + { + BOOST_TEST_EQ( &sv.front(), sv.data() ); + BOOST_TEST_EQ( &sv.back(), sv.data() + sv.size() - 1 ); + } + } + + { + std::string str = "123"; + + boost::core::string_view sv( str ); + + BOOST_TEST_EQ( sv.data(), str.data() ); + BOOST_TEST_EQ( sv.size(), str.size() ); + + BOOST_TEST_EQ( sv.begin(), sv.data() ); + BOOST_TEST_EQ( sv.end(), sv.data() + sv.size() ); + + BOOST_TEST_EQ( sv.cbegin(), sv.data() ); + BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); + + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.begin() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.end() ) ); + + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cbegin() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cend() ) ); + + BOOST_TEST_EQ( sv.length(), sv.size() ); + BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); + + BOOST_TEST_EQ( sv.max_size(), boost::core::string_view::npos ); + + if( !sv.empty() ) + { + BOOST_TEST_EQ( &sv.front(), sv.data() ); + BOOST_TEST_EQ( &sv.back(), sv.data() + sv.size() - 1 ); + } + } + +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) + + { + std::string_view str = "123"; + + boost::core::string_view sv( str ); + + BOOST_TEST_EQ( sv.data(), str.data() ); + BOOST_TEST_EQ( sv.size(), str.size() ); + + BOOST_TEST_EQ( sv.begin(), sv.data() ); + BOOST_TEST_EQ( sv.end(), sv.data() + sv.size() ); + + BOOST_TEST_EQ( sv.cbegin(), sv.data() ); + BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); + + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.begin() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.end() ) ); + + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cbegin() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cend() ) ); + + BOOST_TEST_EQ( sv.length(), sv.size() ); + BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); + + BOOST_TEST_EQ( sv.max_size(), boost::core::string_view::npos ); + + if( !sv.empty() ) + { + BOOST_TEST_EQ( &sv.front(), sv.data() ); + BOOST_TEST_EQ( &sv.back(), sv.data() + sv.size() - 1 ); + } + } + +#endif + + return boost::report_errors(); +} From 016ae92ecfa981182de9573b992f46fc2dd71fc0 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 4 Oct 2021 17:33:04 +0300 Subject: [PATCH 003/258] Add sv_element_access_test --- test/Jamfile.v2 | 1 + test/sv_element_access_test.cpp | 41 +++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 test/sv_element_access_test.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 1ed8fad..31945d0 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -249,6 +249,7 @@ run type_name_test.cpp ; run sv_types_test.cpp ; run sv_construct_test.cpp ; +run sv_element_access_test.cpp ; use-project /boost/core/swap : ./swap ; build-project ./swap ; diff --git a/test/sv_element_access_test.cpp b/test/sv_element_access_test.cpp new file mode 100644 index 0000000..12df69b --- /dev/null +++ b/test/sv_element_access_test.cpp @@ -0,0 +1,41 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include + +int main() +{ + { + boost::core::string_view sv( "12345" ); + + for( std::size_t i = 0; i < 5; ++i ) + { + BOOST_TEST_EQ( &sv[ i ], sv.data() + i ); + BOOST_TEST_EQ( &sv.at( i ), sv.data() + i ); + } + + BOOST_TEST_THROWS( sv.at( 5 ), std::out_of_range ); + BOOST_TEST_THROWS( sv.at( boost::core::string_view::npos ), std::out_of_range ); + } + + { + boost::core::string_view sv; + + BOOST_TEST_THROWS( sv.at( 0 ), std::out_of_range ); + BOOST_TEST_THROWS( sv.at( 1 ), std::out_of_range ); + BOOST_TEST_THROWS( sv.at( boost::core::string_view::npos ), std::out_of_range ); + } + + { + boost::core::string_view sv( "12345", 0 ); + + BOOST_TEST_THROWS( sv.at( 0 ), std::out_of_range ); + BOOST_TEST_THROWS( sv.at( 1 ), std::out_of_range ); + BOOST_TEST_THROWS( sv.at( boost::core::string_view::npos ), std::out_of_range ); + } + + return boost::report_errors(); +} From 964dfe2b745702d07fcbefbfb3b8963135593c55 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 4 Oct 2021 17:45:24 +0300 Subject: [PATCH 004/258] Fix line endings --- include/boost/core/string_view.hpp | 35 +++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index 7857fe1..9009843 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -270,11 +270,13 @@ public: BOOST_CONSTEXPR int compare( size_type pos1, size_type n1, basic_string_view str, size_type pos2, size_type n2 ) const { - return substr( pos1, n1 ).compare( str.substr( pos2, n2 ) ); } + return substr( pos1, n1 ).compare( str.substr( pos2, n2 ) ); + } BOOST_CONSTEXPR int compare( Ch const* s ) const BOOST_NOEXCEPT { - return compare( basic_string_view( s ) ); } + return compare( basic_string_view( s ) ); + } BOOST_CONSTEXPR int compare( size_type pos1, size_type n1, Ch const* s ) const { @@ -283,7 +285,8 @@ public: BOOST_CONSTEXPR int compare( size_type pos1, size_type n1, Ch const* s, size_type n2 ) const { - return substr( pos1, n1 ).compare( basic_string_view( s, n2 ) ); } + return substr( pos1, n1 ).compare( basic_string_view( s, n2 ) ); + } // starts_with @@ -294,7 +297,8 @@ public: BOOST_CONSTEXPR bool starts_with( Ch x ) const BOOST_NOEXCEPT { - return !empty() && front() == x; } + return !empty() && front() == x; + } BOOST_CONSTEXPR bool starts_with( Ch const* x ) const { @@ -305,9 +309,15 @@ public: BOOST_CONSTEXPR bool ends_with( basic_string_view x ) const BOOST_NOEXCEPT { - return size() >= x.size() && compare( size() - x.size(), npos, x ) == 0; } + return size() >= x.size() && compare( size() - x.size(), npos, x ) == 0; + } - BOOST_CONSTEXPR bool ends_with( Ch x ) const BOOST_NOEXCEPT { return !empty() && back() == x; } BOOST_CONSTEXPR bool ends_with( Ch const* x ) const + BOOST_CONSTEXPR bool ends_with( Ch x ) const BOOST_NOEXCEPT + { + return !empty() && back() == x; + } + + BOOST_CONSTEXPR bool ends_with( Ch const* x ) const { return ends_with( basic_string_view( x ) ); } @@ -529,8 +539,17 @@ public: BOOST_CONSTEXPR size_type find_last_not_of( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT { - return find_last_not_of( basic_string_view( s, n ), pos ); } - BOOST_CONSTEXPR size_type find_last_not_of( Ch const* s, size_type pos = npos ) const BOOST_NOEXCEPT { return find_last_not_of( basic_string_view( s ), pos ); } // contains BOOST_CONSTEXPR bool contains( basic_string_view sv ) const BOOST_NOEXCEPT + return find_last_not_of( basic_string_view( s, n ), pos ); + } + + BOOST_CONSTEXPR size_type find_last_not_of( Ch const* s, size_type pos = npos ) const BOOST_NOEXCEPT + { + return find_last_not_of( basic_string_view( s ), pos ); + } + + // contains + + BOOST_CONSTEXPR bool contains( basic_string_view sv ) const BOOST_NOEXCEPT { return find( sv ) != npos; } From 62ba7ca18b440856f961ecbf2258fc220076f1ef Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 4 Oct 2021 19:08:12 +0300 Subject: [PATCH 005/258] Define npos as BOOST_CONSTEXPR_OR_CONST --- include/boost/core/string_view.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index 9009843..f6ba3a1 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -566,7 +566,7 @@ public: }; #if defined(BOOST_NO_CXX17_INLINE_VARIABLES) -template std::size_t const basic_string_view::npos; +template BOOST_CONSTEXPR_OR_CONST std::size_t basic_string_view::npos; #endif typedef basic_string_view string_view; From c8b55f1bde18f85168d810fc290d82b3f91d3da0 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 4 Oct 2021 19:12:05 +0300 Subject: [PATCH 006/258] Change BOOST_CONSTEXPR to BOOST_CXX14_CONSTEXPR appropriately --- include/boost/core/string_view.hpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index f6ba3a1..ae71d72 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -222,7 +222,7 @@ public: // string operations - BOOST_CONSTEXPR size_type copy( Ch* s, size_type n, size_type pos = 0 ) const + BOOST_CXX14_CONSTEXPR size_type copy( Ch* s, size_type n, size_type pos = 0 ) const { if( pos > size() ) { @@ -236,7 +236,7 @@ public: return rlen; } - BOOST_CONSTEXPR basic_string_view substr( size_type pos = 0, size_type n = npos ) const + BOOST_CXX14_CONSTEXPR basic_string_view substr( size_type pos = 0, size_type n = npos ) const { if( pos > size() ) { @@ -250,7 +250,7 @@ public: // compare - BOOST_CONSTEXPR int compare( basic_string_view str ) const BOOST_NOEXCEPT + BOOST_CXX14_CONSTEXPR int compare( basic_string_view str ) const BOOST_NOEXCEPT { std::size_t rlen = std::min( size(), str.size() ); @@ -329,7 +329,7 @@ public: return find( str.data(), pos, str.size() ); } - BOOST_CONSTEXPR size_type find( Ch c, size_type pos = 0 ) const BOOST_NOEXCEPT + BOOST_CXX14_CONSTEXPR size_type find( Ch c, size_type pos = 0 ) const BOOST_NOEXCEPT { if( pos >= size() ) return npos; @@ -338,7 +338,7 @@ public: return r? r - data(): npos; } - BOOST_CONSTEXPR size_type find( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT + BOOST_CXX14_CONSTEXPR size_type find( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT { if( pos + n > size() ) return npos; if( n == 0 ) return pos; @@ -373,7 +373,7 @@ public: return rfind( str.data(), pos, str.size() ); } - BOOST_CONSTEXPR size_type rfind( Ch c, size_type pos = npos ) const BOOST_NOEXCEPT + BOOST_CXX14_CONSTEXPR size_type rfind( Ch c, size_type pos = npos ) const BOOST_NOEXCEPT { if( pos > size() ) { @@ -384,7 +384,7 @@ public: return r == rend()? npos: size() - 1 - ( r - rbegin() ); } - BOOST_CONSTEXPR size_type rfind( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT + BOOST_CXX14_CONSTEXPR size_type rfind( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT { if( n > size() ) return npos; @@ -416,7 +416,7 @@ public: // find_first_of - BOOST_CONSTEXPR size_type find_first_of( basic_string_view str, size_type pos = 0 ) const BOOST_NOEXCEPT + BOOST_CXX14_CONSTEXPR size_type find_first_of( basic_string_view str, size_type pos = 0 ) const BOOST_NOEXCEPT { for( std::size_t i = pos; i < n_; ++i ) { @@ -443,7 +443,7 @@ public: // find_last_of - BOOST_CONSTEXPR size_type find_last_of( basic_string_view str, size_type pos = npos ) const BOOST_NOEXCEPT + BOOST_CXX14_CONSTEXPR size_type find_last_of( basic_string_view str, size_type pos = npos ) const BOOST_NOEXCEPT { if( pos > size() ) { @@ -475,7 +475,7 @@ public: // find_first_not_of - BOOST_CONSTEXPR size_type find_first_not_of( basic_string_view str, size_type pos = 0 ) const BOOST_NOEXCEPT + BOOST_CXX14_CONSTEXPR size_type find_first_not_of( basic_string_view str, size_type pos = 0 ) const BOOST_NOEXCEPT { for( std::size_t i = pos; i < n_; ++i ) { @@ -485,7 +485,7 @@ public: return npos; } - BOOST_CONSTEXPR size_type find_first_not_of( Ch c, size_type pos = 0 ) const BOOST_NOEXCEPT + BOOST_CXX14_CONSTEXPR size_type find_first_not_of( Ch c, size_type pos = 0 ) const BOOST_NOEXCEPT { for( std::size_t i = pos; i < n_; ++i ) { @@ -507,7 +507,7 @@ public: // find_last_not_of - BOOST_CONSTEXPR size_type find_last_not_of( basic_string_view str, size_type pos = npos ) const BOOST_NOEXCEPT + BOOST_CXX14_CONSTEXPR size_type find_last_not_of( basic_string_view str, size_type pos = npos ) const BOOST_NOEXCEPT { if( pos > size() ) { @@ -522,7 +522,7 @@ public: return npos; } - BOOST_CONSTEXPR size_type find_last_not_of( Ch c, size_type pos = npos ) const BOOST_NOEXCEPT + BOOST_CXX14_CONSTEXPR size_type find_last_not_of( Ch c, size_type pos = npos ) const BOOST_NOEXCEPT { if( pos > size() ) { From e206cddc6f06f74106c470cb129af7c2afd46ea5 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 4 Oct 2021 20:27:14 +0300 Subject: [PATCH 007/258] Fix line endings --- doc/string_view.qbk | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/string_view.qbk b/doc/string_view.qbk index e92c295..128c906 100644 --- a/doc/string_view.qbk +++ b/doc/string_view.qbk @@ -120,7 +120,8 @@ public: constexpr bool starts_with( Ch const* x ) const; constexpr bool ends_with( basic_string_view x ) const noexcept; - constexpr bool ends_with( Ch x ) const noexcept; constexpr bool ends_with( Ch const* x ) const; + constexpr bool ends_with( Ch x ) const noexcept; + constexpr bool ends_with( Ch const* x ) const; // searching @@ -152,7 +153,8 @@ public: constexpr size_type find_last_not_of( basic_string_view s, size_type pos = npos ) const noexcept; constexpr size_type find_last_not_of( Ch c, size_type pos = npos ) const noexcept; constexpr size_type find_last_not_of( Ch const* s, size_type pos, size_type n ) const; - constexpr size_type find_last_not_of( Ch const* s, size_type pos = npos ) const; }; + constexpr size_type find_last_not_of( Ch const* s, size_type pos = npos ) const; +}; typedef basic_string_view string_view; typedef basic_string_view wstring_view; From 1aa8341bd76fdec7ddb10662badab7fa6e10d55a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 4 Oct 2021 20:36:40 +0300 Subject: [PATCH 008/258] Add sv_modifiers_test --- test/Jamfile.v2 | 1 + test/sv_modifiers_test.cpp | 127 +++++++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 test/sv_modifiers_test.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 31945d0..24a5134 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -250,6 +250,7 @@ run type_name_test.cpp ; run sv_types_test.cpp ; run sv_construct_test.cpp ; run sv_element_access_test.cpp ; +run sv_modifiers_test.cpp ; use-project /boost/core/swap : ./swap ; build-project ./swap ; diff --git a/test/sv_modifiers_test.cpp b/test/sv_modifiers_test.cpp new file mode 100644 index 0000000..d292594 --- /dev/null +++ b/test/sv_modifiers_test.cpp @@ -0,0 +1,127 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include + +int main() +{ + { + char const* s1 = "12345"; + char const* s2 = ""; + + boost::core::string_view sv1( s1 ); + boost::core::string_view sv2( s2 ); + + sv1.swap( sv2 ); + + BOOST_TEST_EQ( sv1.data(), s2 ); + BOOST_TEST_EQ( sv1.size(), 0 ); + + BOOST_TEST_EQ( sv2.data(), s1 ); + BOOST_TEST_EQ( sv2.size(), 5); + } + + { + boost::core::string_view sv; + + char const* data = sv.data(); + std::size_t size = sv.size(); + + sv.remove_prefix( 0 ); + + BOOST_TEST_EQ( sv.data(), data ); + BOOST_TEST_EQ( sv.size(), size ); + + sv.remove_suffix( 0 ); + + BOOST_TEST_EQ( sv.data(), data ); + BOOST_TEST_EQ( sv.size(), size ); + } + + { + boost::core::string_view sv( "" ); + + char const* data = sv.data(); + std::size_t size = sv.size(); + + sv.remove_prefix( 0 ); + + BOOST_TEST_EQ( sv.data(), data ); + BOOST_TEST_EQ( sv.size(), size ); + + sv.remove_suffix( 0 ); + + BOOST_TEST_EQ( sv.data(), data ); + BOOST_TEST_EQ( sv.size(), size ); + } + + { + boost::core::string_view sv( "12345" ); + + char const* data = sv.data(); + std::size_t size = sv.size(); + + sv.remove_prefix( 0 ); + + BOOST_TEST_EQ( sv.data(), data ); + BOOST_TEST_EQ( sv.size(), size ); + + sv.remove_suffix( 0 ); + + BOOST_TEST_EQ( sv.data(), data ); + BOOST_TEST_EQ( sv.size(), size ); + } + + { + boost::core::string_view sv( "12345" ); + + char const* data = sv.data(); + std::size_t size = sv.size(); + + sv.remove_prefix( 2 ); + + BOOST_TEST_EQ( sv.data(), data + 2 ); + BOOST_TEST_EQ( sv.size(), size - 2 ); + } + + { + boost::core::string_view sv( "12345" ); + + char const* data = sv.data(); + std::size_t size = sv.size(); + + sv.remove_prefix( 5 ); + + BOOST_TEST_EQ( sv.data(), data + 5 ); + BOOST_TEST_EQ( sv.size(), size - 5 ); + } + + { + boost::core::string_view sv( "12345" ); + + char const* data = sv.data(); + std::size_t size = sv.size(); + + sv.remove_suffix( 2 ); + + BOOST_TEST_EQ( sv.data(), data ); + BOOST_TEST_EQ( sv.size(), size - 2 ); + } + + { + boost::core::string_view sv( "12345" ); + + char const* data = sv.data(); + std::size_t size = sv.size(); + + sv.remove_suffix( 5 ); + + BOOST_TEST_EQ( sv.data(), data ); + BOOST_TEST_EQ( sv.size(), size - 5 ); + } + + return boost::report_errors(); +} From c65c05c0060209039645f46a19f18fae1e9b6bc4 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 4 Oct 2021 20:45:10 +0300 Subject: [PATCH 009/258] Add sv_copy_test --- test/Jamfile.v2 | 1 + test/sv_copy_test.cpp | 50 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 test/sv_copy_test.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 24a5134..6b179e1 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -251,6 +251,7 @@ run sv_types_test.cpp ; run sv_construct_test.cpp ; run sv_element_access_test.cpp ; run sv_modifiers_test.cpp ; +run sv_copy_test.cpp ; use-project /boost/core/swap : ./swap ; build-project ./swap ; diff --git a/test/sv_copy_test.cpp b/test/sv_copy_test.cpp new file mode 100644 index 0000000..710718b --- /dev/null +++ b/test/sv_copy_test.cpp @@ -0,0 +1,50 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +int main() +{ + { + boost::core::string_view sv; + + BOOST_TEST_EQ( sv.copy( 0, 0 ), 0 ); + BOOST_TEST_EQ( sv.copy( 0, 0, 0 ), 0 ); + BOOST_TEST_THROWS( sv.copy( 0, 0, 1 ), std::out_of_range ); + BOOST_TEST_THROWS( sv.copy( 0, 0, boost::core::string_view::npos ), std::out_of_range ); + } + + { + boost::core::string_view sv( "12345" ); + char buffer[ 8 ] = {}; + + BOOST_TEST_EQ( sv.copy( buffer, 0 ), 0 ); + BOOST_TEST_EQ( buffer[0], 0 ); + + BOOST_TEST_EQ( sv.copy( buffer, 0, 0 ), 0 ); + BOOST_TEST_EQ( buffer[0], 0 ); + + BOOST_TEST_EQ( sv.copy( buffer, 0, 1 ), 0 ); + BOOST_TEST_EQ( buffer[0], 0 ); + + BOOST_TEST_THROWS( sv.copy( buffer, 0, boost::core::string_view::npos ), std::out_of_range ); + BOOST_TEST_EQ( buffer[0], 0 ); + + BOOST_TEST_EQ( sv.copy( buffer, 1 ), 1 ); + BOOST_TEST_EQ( buffer[0], '1' ); + BOOST_TEST_EQ( buffer[1], 0 ); + + BOOST_TEST_EQ( sv.copy( buffer, 1, 1 ), 1 ); + BOOST_TEST_EQ( buffer[0], '2' ); + BOOST_TEST_EQ( buffer[1], 0 ); + + BOOST_TEST_EQ( sv.copy( buffer, 8 ), 5 ); + BOOST_TEST_CSTR_EQ( buffer, "12345" ); + } + + return boost::report_errors(); +} From 042bb981424adb24f1aed71806b23a1a48c68aa5 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 4 Oct 2021 20:57:10 +0300 Subject: [PATCH 010/258] Add sv_substr_test --- test/Jamfile.v2 | 1 + test/sv_substr_test.cpp | 203 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 204 insertions(+) create mode 100644 test/sv_substr_test.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 6b179e1..bf59485 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -252,6 +252,7 @@ run sv_construct_test.cpp ; run sv_element_access_test.cpp ; run sv_modifiers_test.cpp ; run sv_copy_test.cpp ; +run sv_substr_test.cpp ; use-project /boost/core/swap : ./swap ; build-project ./swap ; diff --git a/test/sv_substr_test.cpp b/test/sv_substr_test.cpp new file mode 100644 index 0000000..666aebf --- /dev/null +++ b/test/sv_substr_test.cpp @@ -0,0 +1,203 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +int main() +{ + { + boost::core::string_view sv; + + { + boost::core::string_view sv2 = sv.substr(); + + BOOST_TEST_EQ( sv2.data(), sv.data() ); + BOOST_TEST_EQ( sv2.size(), sv.size() ); + } + + { + boost::core::string_view sv2 = sv.substr( 0 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() ); + BOOST_TEST_EQ( sv2.size(), sv.size() ); + } + + BOOST_TEST_THROWS( sv.substr( 1 ), std::out_of_range ); + BOOST_TEST_THROWS( sv.substr( boost::core::string_view::npos ), std::out_of_range ); + + { + boost::core::string_view sv2 = sv.substr( 0, 1 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() ); + BOOST_TEST_EQ( sv2.size(), sv.size() ); + } + + { + boost::core::string_view sv2 = sv.substr( 0, 0 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() ); + BOOST_TEST_EQ( sv2.size(), sv.size() ); + } + + BOOST_TEST_THROWS( sv.substr( 1, 0 ), std::out_of_range ); + BOOST_TEST_THROWS( sv.substr( boost::core::string_view::npos, 0 ), std::out_of_range ); + } + + { + boost::core::string_view sv( "12345" ); + + { + boost::core::string_view sv2 = sv.substr(); + + BOOST_TEST_EQ( sv2.data(), sv.data() ); + BOOST_TEST_EQ( sv2.size(), sv.size() ); + } + + { + boost::core::string_view sv2 = sv.substr( 0 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() ); + BOOST_TEST_EQ( sv2.size(), sv.size() ); + } + + { + boost::core::string_view sv2 = sv.substr( 2 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() + 2 ); + BOOST_TEST_EQ( sv2.size(), sv.size() - 2 ); + } + + { + boost::core::string_view sv2 = sv.substr( 5 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() + 5 ); + BOOST_TEST_EQ( sv2.size(), sv.size() - 5 ); + } + + BOOST_TEST_THROWS( sv.substr( 6 ), std::out_of_range ); + BOOST_TEST_THROWS( sv.substr( boost::core::string_view::npos ), std::out_of_range ); + + { + boost::core::string_view sv2 = sv.substr( 0, 0 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() ); + BOOST_TEST_EQ( sv2.size(), 0 ); + } + + { + boost::core::string_view sv2 = sv.substr( 2, 0 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() + 2 ); + BOOST_TEST_EQ( sv2.size(), 0 ); + } + + { + boost::core::string_view sv2 = sv.substr( 5, 0 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() + 5 ); + BOOST_TEST_EQ( sv2.size(), 0 ); + } + + BOOST_TEST_THROWS( sv.substr( 6, 0 ), std::out_of_range ); + BOOST_TEST_THROWS( sv.substr( boost::core::string_view::npos, 0 ), std::out_of_range ); + + { + boost::core::string_view sv2 = sv.substr( 0, 3 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() ); + BOOST_TEST_EQ( sv2.size(), 3 ); + } + + { + boost::core::string_view sv2 = sv.substr( 2, 3 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() + 2 ); + BOOST_TEST_EQ( sv2.size(), 3 ); + } + + { + boost::core::string_view sv2 = sv.substr( 4, 3 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() + 4 ); + BOOST_TEST_EQ( sv2.size(), 1 ); + } + + { + boost::core::string_view sv2 = sv.substr( 5, 3 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() + 5 ); + BOOST_TEST_EQ( sv2.size(), 0 ); + } + + BOOST_TEST_THROWS( sv.substr( 6, 3 ), std::out_of_range ); + BOOST_TEST_THROWS( sv.substr( boost::core::string_view::npos, 3 ), std::out_of_range ); + + { + boost::core::string_view sv2 = sv.substr( 0, 5 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() ); + BOOST_TEST_EQ( sv2.size(), 5 ); + } + + { + boost::core::string_view sv2 = sv.substr( 2, 5 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() + 2 ); + BOOST_TEST_EQ( sv2.size(), 3 ); + } + + { + boost::core::string_view sv2 = sv.substr( 4, 5 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() + 4 ); + BOOST_TEST_EQ( sv2.size(), 1 ); + } + + { + boost::core::string_view sv2 = sv.substr( 5, 5 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() + 5 ); + BOOST_TEST_EQ( sv2.size(), 0 ); + } + + BOOST_TEST_THROWS( sv.substr( 6, 5 ), std::out_of_range ); + BOOST_TEST_THROWS( sv.substr( boost::core::string_view::npos, 5 ), std::out_of_range ); + + { + boost::core::string_view sv2 = sv.substr( 0, 8 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() ); + BOOST_TEST_EQ( sv2.size(), 5 ); + } + + { + boost::core::string_view sv2 = sv.substr( 2, 8 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() + 2 ); + BOOST_TEST_EQ( sv2.size(), 3 ); + } + + { + boost::core::string_view sv2 = sv.substr( 4, 8 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() + 4 ); + BOOST_TEST_EQ( sv2.size(), 1 ); + } + + { + boost::core::string_view sv2 = sv.substr( 5, 8 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() + 5 ); + BOOST_TEST_EQ( sv2.size(), 0 ); + } + + BOOST_TEST_THROWS( sv.substr( 6, 8 ), std::out_of_range ); + BOOST_TEST_THROWS( sv.substr( boost::core::string_view::npos, 8 ), std::out_of_range ); + } + + return boost::report_errors(); +} From 31e2caef12fd90db7a6014efe49f5c990bdc9e83 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 4 Oct 2021 22:11:14 +0300 Subject: [PATCH 011/258] Add sv_compare_test --- test/Jamfile.v2 | 1 + test/sv_compare_test.cpp | 145 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 test/sv_compare_test.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index bf59485..43ce2d9 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -253,6 +253,7 @@ run sv_element_access_test.cpp ; run sv_modifiers_test.cpp ; run sv_copy_test.cpp ; run sv_substr_test.cpp ; +run sv_compare_test.cpp ; use-project /boost/core/swap : ./swap ; build-project ./swap ; diff --git a/test/sv_compare_test.cpp b/test/sv_compare_test.cpp new file mode 100644 index 0000000..26eba68 --- /dev/null +++ b/test/sv_compare_test.cpp @@ -0,0 +1,145 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +int main() +{ + std::size_t const npos = boost::core::string_view::npos; + + { + boost::core::string_view sv1( "" ); + boost::core::string_view sv2( "" ); + + BOOST_TEST_EQ( sv1.compare( sv2 ), 0 ); + + BOOST_TEST_EQ( sv1.compare( 0, 0, sv2 ), 0 ); + BOOST_TEST_EQ( sv1.compare( 0, 1, sv2 ), 0 ); + + BOOST_TEST_THROWS( sv1.compare( 1, 0, sv2 ), std::out_of_range ); + BOOST_TEST_THROWS( sv1.compare( 1, 1, sv2 ), std::out_of_range ); + BOOST_TEST_THROWS( sv1.compare( 1, npos, sv2 ), std::out_of_range ); + + BOOST_TEST_EQ( sv1.compare( 0, 0, sv2, 0, 0 ), 0 ); + BOOST_TEST_EQ( sv1.compare( 0, 1, sv2, 0, 1 ), 0 ); + + BOOST_TEST_THROWS( sv1.compare( 1, 0, sv2, 0, 0 ), std::out_of_range ); + BOOST_TEST_THROWS( sv1.compare( 1, 1, sv2, 0, 1 ), std::out_of_range ); + + BOOST_TEST_THROWS( sv1.compare( 0, 0, sv2, 1, 0 ), std::out_of_range ); + BOOST_TEST_THROWS( sv1.compare( 0, 1, sv2, 1, 1 ), std::out_of_range ); + + BOOST_TEST_EQ( sv1.compare( "" ), 0 ); + BOOST_TEST_LT( sv1.compare( "1" ), 0 ); + + BOOST_TEST_EQ( sv1.compare( 0, 0, "" ), 0 ); + BOOST_TEST_LT( sv1.compare( 0, 0, "1" ), 0 ); + + BOOST_TEST_EQ( sv1.compare( 0, 1, "" ), 0 ); + BOOST_TEST_LT( sv1.compare( 0, 1, "1" ), 0 ); + + BOOST_TEST_THROWS( sv1.compare( 1, 0, "" ), std::out_of_range ); + BOOST_TEST_THROWS( sv1.compare( 1, 1, "1" ), std::out_of_range ); + + BOOST_TEST_EQ( sv1.compare( 0, 0, "", 0 ), 0 ); + BOOST_TEST_EQ( sv1.compare( 0, 0, "1", 0 ), 0 ); + BOOST_TEST_LT( sv1.compare( 0, 0, "1", 1 ), 0 ); + + BOOST_TEST_EQ( sv1.compare( 0, 1, "", 0 ), 0 ); + BOOST_TEST_EQ( sv1.compare( 0, 1, "1", 0 ), 0 ); + BOOST_TEST_LT( sv1.compare( 0, 1, "1", 1 ), 0 ); + + BOOST_TEST_THROWS( sv1.compare( 1, 0, "", 0 ), std::out_of_range ); + BOOST_TEST_THROWS( sv1.compare( 1, 1, "1", 0 ), std::out_of_range ); + BOOST_TEST_THROWS( sv1.compare( 1, 1, "1", 1 ), std::out_of_range ); + } + + { + boost::core::string_view sv1( "123412345" ); + boost::core::string_view sv2( "1234" ); + + BOOST_TEST_GT( sv1.compare( sv2 ), 0 ); + + BOOST_TEST_LT( sv1.compare( 0, 3, sv2 ), 0 ); + BOOST_TEST_EQ( sv1.compare( 0, 4, sv2 ), 0 ); + BOOST_TEST_GT( sv1.compare( 0, 5, sv2 ), 0 ); + BOOST_TEST_GT( sv1.compare( 0, npos, sv2 ), 0 ); + + BOOST_TEST_LT( sv1.compare( 1, 0, sv2 ), 0 ); + BOOST_TEST_GT( sv1.compare( 1, 1, sv2 ), 0 ); + + BOOST_TEST_LT( sv1.compare( 4, 3, sv2 ), 0 ); + BOOST_TEST_EQ( sv1.compare( 4, 4, sv2 ), 0 ); + BOOST_TEST_GT( sv1.compare( 4, 5, sv2 ), 0 ); + + BOOST_TEST_LT( sv1.compare( 9, 0, sv2 ), 0 ); + BOOST_TEST_LT( sv1.compare( 9, 1, sv2 ), 0 ); + + BOOST_TEST_THROWS( sv1.compare( 10, 0, sv2 ), std::out_of_range ); + BOOST_TEST_THROWS( sv1.compare( 10, 1, sv2 ), std::out_of_range ); + + BOOST_TEST_GT( sv1.compare( 0, 3, sv2, 0, 2 ), 0 ); + BOOST_TEST_EQ( sv1.compare( 0, 3, sv2, 0, 3 ), 0 ); + BOOST_TEST_LT( sv1.compare( 0, 3, sv2, 0, 4 ), 0 ); + BOOST_TEST_LT( sv1.compare( 0, 3, sv2, 0, 5 ), 0 ); + + BOOST_TEST_GT( sv1.compare( 0, 4, sv2, 0, 3 ), 0 ); + BOOST_TEST_EQ( sv1.compare( 0, 4, sv2, 0, 4 ), 0 ); + BOOST_TEST_EQ( sv1.compare( 0, 4, sv2, 0, 5 ), 0 ); + + BOOST_TEST_LT( sv1.compare( 5, 2, sv2, 1, npos ), 0 ); + BOOST_TEST_EQ( sv1.compare( 5, 3, sv2, 1, npos ), 0 ); + BOOST_TEST_GT( sv1.compare( 5, 4, sv2, 1, npos ), 0 ); + + BOOST_TEST_EQ( sv1.compare( 9, 0, sv2, 0, 0 ), 0 ); + BOOST_TEST_LT( sv1.compare( 9, 1, sv2, 0, 1 ), 0 ); + + BOOST_TEST_THROWS( sv1.compare( 10, 0, sv2, 0, 0 ), std::out_of_range ); + BOOST_TEST_THROWS( sv1.compare( 10, 1, sv2, 0, 1 ), std::out_of_range ); + + BOOST_TEST_EQ( sv1.compare( 0, 0, sv2, 4, 0 ), 0 ); + BOOST_TEST_GT( sv1.compare( 0, 1, sv2, 4, 1 ), 0 ); + + BOOST_TEST_THROWS( sv1.compare( 0, 0, sv2, 5, 0 ), std::out_of_range ); + BOOST_TEST_THROWS( sv1.compare( 0, 1, sv2, 5, 1 ), std::out_of_range ); + + BOOST_TEST_GT( sv1.compare( "" ), 0 ); + BOOST_TEST_GT( sv1.compare( "12341234" ), 0 ); + BOOST_TEST_GT( sv1.compare( "123412344" ), 0 ); + BOOST_TEST_EQ( sv1.compare( "123412345" ), 0 ); + BOOST_TEST_LT( sv1.compare( "123412346" ), 0 ); + BOOST_TEST_LT( sv1.compare( "1234123456" ), 0 ); + + BOOST_TEST_GT( sv1.compare( 4, 3, "" ), 0 ); + BOOST_TEST_GT( sv1.compare( 4, 3, "1" ), 0 ); + BOOST_TEST_GT( sv1.compare( 4, 3, "12" ), 0 ); + BOOST_TEST_GT( sv1.compare( 4, 3, "122" ), 0 ); + BOOST_TEST_EQ( sv1.compare( 4, 3, "123" ), 0 ); + BOOST_TEST_LT( sv1.compare( 4, 3, "124" ), 0 ); + BOOST_TEST_LT( sv1.compare( 4, 3, "1234" ), 0 ); + + BOOST_TEST_EQ( sv1.compare( 9, 0, "" ), 0 ); + BOOST_TEST_LT( sv1.compare( 9, 1, "1" ), 0 ); + + BOOST_TEST_THROWS( sv1.compare( 10, 0, "" ), std::out_of_range ); + BOOST_TEST_THROWS( sv1.compare( 10, 1, "1" ), std::out_of_range ); + + BOOST_TEST_GT( sv1.compare( 4, npos, "123456", 4 ), 0 ); + BOOST_TEST_EQ( sv1.compare( 4, npos, "123456", 5 ), 0 ); + BOOST_TEST_LT( sv1.compare( 4, npos, "123456", 6 ), 0 ); + + BOOST_TEST_EQ( sv1.compare( 9, npos, "", 0 ), 0 ); + BOOST_TEST_EQ( sv1.compare( 9, npos, "1", 0 ), 0 ); + BOOST_TEST_LT( sv1.compare( 9, npos, "1", 1 ), 0 ); + + BOOST_TEST_THROWS( sv1.compare( 10, npos, "", 0 ), std::out_of_range ); + BOOST_TEST_THROWS( sv1.compare( 10, npos, "1", 0 ), std::out_of_range ); + BOOST_TEST_THROWS( sv1.compare( 10, npos, "1", 1 ), std::out_of_range ); + } + + return boost::report_errors(); +} From 290340fd27011d48f4e209921d76928e33a0b1f6 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 5 Oct 2021 04:58:52 +0300 Subject: [PATCH 012/258] Use core::type_name in lightweight_test_trait --- include/boost/core/lightweight_test_trait.hpp | 56 ++----------------- 1 file changed, 5 insertions(+), 51 deletions(-) diff --git a/include/boost/core/lightweight_test_trait.hpp b/include/boost/core/lightweight_test_trait.hpp index bddc3ce..77a1fcd 100644 --- a/include/boost/core/lightweight_test_trait.hpp +++ b/include/boost/core/lightweight_test_trait.hpp @@ -11,7 +11,7 @@ // // BOOST_TEST_TRAIT_TRUE, BOOST_TEST_TRAIT_FALSE, BOOST_TEST_TRAIT_SAME // -// Copyright 2014 Peter Dimov +// Copyright 2014, 2021 Peter Dimov // // Copyright 2019 Glen Joseph Fernandes // (glenjofe@gmail.com) @@ -21,60 +21,15 @@ // http://www.boost.org/LICENSE_1_0.txt #include -#include +#include #include #include namespace boost { - namespace detail { -template struct test_print { }; - -template inline std::ostream& operator<<(std::ostream& o, test_print) -{ - return o << boost::core::demangled_name(BOOST_CORE_TYPEID(T)); -} - -template inline std::ostream& operator<<(std::ostream& o, test_print) -{ - return o << test_print(); -} - -template inline std::ostream& operator<<(std::ostream& o, test_print) -{ - return o << test_print() << " const"; -} - -template inline std::ostream& operator<<(std::ostream& o, test_print) -{ - return o << test_print() << " volatile"; -} - -template inline std::ostream& operator<<(std::ostream& o, test_print) -{ - return o << test_print() << " const volatile"; -} - -template inline std::ostream& operator<<(std::ostream& o, test_print) -{ - return o << test_print(); -} - -template inline std::ostream& operator<<(std::ostream& o, test_print) -{ - return o << test_print() << " &"; -} - -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) -template inline std::ostream& operator<<(std::ostream& o, test_print) -{ - return o << test_print() << " &&"; -} -#endif - template< class T > inline void test_trait_impl( char const * trait, void (*)( T ), bool expected, char const * file, int line, char const * function ) { @@ -86,7 +41,7 @@ template< class T > inline void test_trait_impl( char const * trait, void (*)( T { BOOST_LIGHTWEIGHT_TEST_OSTREAM << file << "(" << line << "): predicate '" << trait << "' [" - << boost::core::demangled_name( BOOST_CORE_TYPEID(T) ) << "]" + << boost::core::type_name() << "]" << " test failed in function '" << function << "' (should have been " << ( expected? "true": "false" ) << ")" << std::endl; @@ -112,8 +67,8 @@ template inline void test_trait_same_impl( char const * type BOOST_LIGHTWEIGHT_TEST_OSTREAM << file << "(" << line << "): test 'is_same<" << types << ">'" << " failed in function '" << function - << "' ('" << test_print() - << "' != '" << test_print() << "')" + << "' ('" << boost::core::type_name() + << "' != '" << boost::core::type_name() << "')" << std::endl; ++test_results().errors(); @@ -121,7 +76,6 @@ template inline void test_trait_same_impl( char const * type } } // namespace detail - } // namespace boost #define BOOST_TEST_TRAIT_TRUE(type) ( ::boost::detail::test_trait_impl(#type, (void(*)type)0, true, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION) ) From 36cec9a5cc8e2eddea8d192991310bc813901499 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 5 Oct 2021 05:01:05 +0300 Subject: [PATCH 013/258] Handle references to functions --- include/boost/core/type_name.hpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/boost/core/type_name.hpp b/include/boost/core/type_name.hpp index 9a82dd3..33e717f 100644 --- a/include/boost/core/type_name.hpp +++ b/include/boost/core/type_name.hpp @@ -332,6 +332,22 @@ template std::string type_name( tn_identity ) #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +// function references + +template std::string type_name( tn_identity ) +{ + return type_name( tn_identity() ) + "(&)(" + tn_add_each() + ')'; +} + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + +template std::string type_name( tn_identity ) +{ + return type_name( tn_identity() ) + "(&&)(" + tn_add_each() + ')'; +} + +#endif + // function pointers template std::string type_name( tn_identity ) From 01bd23df5d30801deea2c16c30c3b95a6a6c89f0 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 5 Oct 2021 05:04:56 +0300 Subject: [PATCH 014/258] Add tests for function types --- test/type_name_test.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/type_name_test.cpp b/test/type_name_test.cpp index 6ab08f5..52a74a5 100644 --- a/test/type_name_test.cpp +++ b/test/type_name_test.cpp @@ -105,6 +105,18 @@ int main() TEST(void*); TEST(void const* volatile*); + TEST(void()); + TEST(int(float, A, B*)); + + TEST(void(*)()); + TEST(void(&)()); + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + + TEST(void(&&)()); + +#endif + TEST(A[]); TEST(A const[]); TEST(A volatile[]); From b93317815c7b62551e34e13253008d2d56817148 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 5 Oct 2021 05:30:37 +0300 Subject: [PATCH 015/258] Apply msvc-12.0 (and below) workarounds --- include/boost/core/type_name.hpp | 25 ++++++++++++++++++++++--- test/type_name_test.cpp | 3 +++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/include/boost/core/type_name.hpp b/include/boost/core/type_name.hpp index 33e717f..dfdedd3 100644 --- a/include/boost/core/type_name.hpp +++ b/include/boost/core/type_name.hpp @@ -14,6 +14,7 @@ // https://www.boost.org/LICENSE_1_0.txt #include +#include #include #include #include @@ -73,6 +74,24 @@ template struct tn_is_reference #endif +// tn_remove_const + +template struct tn_remove_const +{ + typedef T type; +}; + +template struct tn_remove_const +{ + typedef T type; +}; + +// tn_is_function (also catches references but that's OK) + +template::type> struct tn_is_function: core::is_same +{ +}; + #if !defined(BOOST_NO_TYPEID) // typeid_name @@ -261,21 +280,21 @@ template std::string type_name( tn_identity ) #else template -typename tn_enable_if::value, std::string>::type +typename tn_enable_if::value, std::string>::type type_name( tn_identity ) { return type_name( tn_identity() ) + " const"; } template -typename tn_enable_if::value, std::string>::type +typename tn_enable_if::value, std::string>::type type_name( tn_identity ) { return type_name( tn_identity() ) + " volatile"; } template -typename tn_enable_if::value, std::string>::type +typename tn_enable_if::value, std::string>::type type_name( tn_identity ) { return type_name( tn_identity() ) + " const volatile"; diff --git a/test/type_name_test.cpp b/test/type_name_test.cpp index 52a74a5..b3439c1 100644 --- a/test/type_name_test.cpp +++ b/test/type_name_test.cpp @@ -105,6 +105,8 @@ int main() TEST(void*); TEST(void const* volatile*); +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + TEST(void()); TEST(int(float, A, B*)); @@ -115,6 +117,7 @@ int main() TEST(void(&&)()); +#endif #endif TEST(A[]); From f833040d4835f803006c0e0883f0e21ae8cfe8ac Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 5 Oct 2021 05:42:41 +0300 Subject: [PATCH 016/258] Disable msvc warnings around tn_is_function --- include/boost/core/type_name.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/boost/core/type_name.hpp b/include/boost/core/type_name.hpp index dfdedd3..8632f81 100644 --- a/include/boost/core/type_name.hpp +++ b/include/boost/core/type_name.hpp @@ -88,10 +88,19 @@ template struct tn_remove_const // tn_is_function (also catches references but that's OK) +#if defined(BOOST_MSVC) +# pragma warning(push) +# pragma warning(disable: 4180 4181) +#endif + template::type> struct tn_is_function: core::is_same { }; +#if defined(BOOST_MSVC) +# pragma warning(pop) +#endif + #if !defined(BOOST_NO_TYPEID) // typeid_name From ccdf5ce031df3ad10c36d520e75fe126d0b19166 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 5 Oct 2021 06:45:41 +0300 Subject: [PATCH 017/258] Track the type suffix independently for better decomposition of functions and arrays --- include/boost/core/type_name.hpp | 267 ++++++++++++++----------------- test/type_name_test.cpp | 18 +++ 2 files changed, 136 insertions(+), 149 deletions(-) diff --git a/include/boost/core/type_name.hpp b/include/boost/core/type_name.hpp index 8632f81..d31750b 100644 --- a/include/boost/core/type_name.hpp +++ b/include/boost/core/type_name.hpp @@ -244,7 +244,7 @@ inline std::string tn_to_string( std::size_t n ) template int tn_add_each_impl( std::string& st ) { if( !st.empty() ) st += ", "; - st += type_name( tn_identity() ); + st += type_name( tn_identity(), "" ); return 0; }; @@ -262,51 +262,51 @@ template std::string tn_add_each() // primary -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return typeid_name(); + return typeid_name() + suffix; } // cv #if !defined(BOOST_MSVC) || BOOST_MSVC >= 1900 -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return type_name( tn_identity() ) + " const"; + return type_name( tn_identity(), " const" + suffix ); } -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return type_name( tn_identity() ) + " volatile"; + return type_name( tn_identity(), " volatile" + suffix ); } -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return type_name( tn_identity() ) + " const volatile"; + return type_name( tn_identity(), " const volatile" + suffix ); } #else template typename tn_enable_if::value, std::string>::type -type_name( tn_identity ) +type_name( tn_identity, std::string const& suffix ) { - return type_name( tn_identity() ) + " const"; + return type_name( tn_identity(), " const" + suffix ); } template typename tn_enable_if::value, std::string>::type -type_name( tn_identity ) +type_name( tn_identity, std::string const& suffix ) { - return type_name( tn_identity() ) + " volatile"; + return type_name( tn_identity(), " volatile" + suffix ); } template typename tn_enable_if::value, std::string>::type -type_name( tn_identity ) +type_name( tn_identity, std::string const& suffix ) { - return type_name( tn_identity() ) + " const volatile"; + return type_name( tn_identity(), " const volatile" + suffix ); } #endif @@ -315,27 +315,27 @@ type_name( tn_identity ) #if !defined(BOOST_MSVC) || BOOST_MSVC >= 1900 -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return type_name( tn_identity() ) + "&"; + return type_name( tn_identity(), "&" + suffix ); } #else template typename tn_enable_if::value, std::string>::type -type_name( tn_identity ) +type_name( tn_identity, std::string const& suffix ) { - return type_name( tn_identity() ) + "&"; + return type_name( tn_identity(), "&" + suffix ); } #endif #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return type_name( tn_identity() ) + "&&"; + return type_name( tn_identity(), "&&" + suffix ); } #endif @@ -344,81 +344,34 @@ template std::string type_name( tn_identity ) #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return type_name( tn_identity() ) + '(' + tn_add_each() + ')'; + std::string r = type_name( tn_identity(), "" ); + + if( !suffix.empty() ) + { + r += '(' + suffix + ')'; + } + + r += '(' + tn_add_each() + ')'; + + return r; } #endif // pointers -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return type_name( tn_identity() ) + "*"; + return type_name( tn_identity(), "*" + suffix ); } -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - -// function references - -template std::string type_name( tn_identity ) -{ - return type_name( tn_identity() ) + "(&)(" + tn_add_each() + ')'; -} - -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - -template std::string type_name( tn_identity ) -{ - return type_name( tn_identity() ) + "(&&)(" + tn_add_each() + ')'; -} - -#endif - -// function pointers - -template std::string type_name( tn_identity ) -{ - return type_name( tn_identity() ) + "(*)(" + tn_add_each() + ')'; -} - -template std::string type_name( tn_identity ) -{ - return type_name( tn_identity() ) + "(*&)(" + tn_add_each() + ')'; -} - -template std::string type_name( tn_identity ) -{ - return type_name( tn_identity() ) + "(* const)(" + tn_add_each() + ')'; -} - -template std::string type_name( tn_identity ) -{ - return type_name( tn_identity() ) + "(* const&)(" + tn_add_each() + ')'; -} - -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - -template std::string type_name( tn_identity ) -{ - return type_name( tn_identity() ) + "(*&&)(" + tn_add_each() + ')'; -} - -template std::string type_name( tn_identity ) -{ - return type_name( tn_identity() ) + "(* const&&)(" + tn_add_each() + ')'; -} - -#endif - -#endif - // arrays template std::pair array_prefix_suffix( tn_identity ) { - return std::pair( type_name( tn_identity() ), "" ); + return std::pair( type_name( tn_identity(), "" ), "" ); } template std::pair array_prefix_suffix( tn_identity ) @@ -430,163 +383,179 @@ template std::pair array_prefi return r; } -template std::string array_type_name( tn_identity ) +template std::string array_type_name( tn_identity, std::string const& suffix ) { std::pair r = array_prefix_suffix( tn_identity() ); - return r.first + "[]" + r.second; + + if( suffix.empty() ) + { + return r.first + "[]" + r.second; + } + else + { + return r.first + '(' + suffix + ")[]" + r.second; + } } -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return array_type_name( tn_identity() ); + return array_type_name( tn_identity(), suffix ); } -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return array_type_name( tn_identity() ); + return array_type_name( tn_identity(), suffix ); } -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return array_type_name( tn_identity() ); + return array_type_name( tn_identity(), suffix ); } -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return array_type_name( tn_identity() ); + return array_type_name( tn_identity(), suffix ); } -template std::string array_type_name( tn_identity ) +template std::string array_type_name( tn_identity, std::string const& suffix ) { std::pair r = array_prefix_suffix( tn_identity() ); - return r.first + r.second; + + if( suffix.empty() ) + { + return r.first + r.second; + } + else + { + return r.first + '(' + suffix + ")" + r.second; + } } -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return array_type_name( tn_identity() ); + return array_type_name( tn_identity(), suffix ); } -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return array_type_name( tn_identity() ); + return array_type_name( tn_identity(), suffix ); } -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return array_type_name( tn_identity() ); + return array_type_name( tn_identity(), suffix ); } -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return array_type_name( tn_identity() ); + return array_type_name( tn_identity(), suffix ); } // nullptr_t #if !defined(BOOST_NO_CXX11_NULLPTR) -inline std::string type_name( tn_identity ) +inline std::string type_name( tn_identity, std::string const& suffix ) { - return "std::nullptr_t"; + return "std::nullptr_t" + suffix; } #endif // strings -template class L, class Ch> std::string type_name( tn_identity< L, std::allocator > > ) +template class L, class Ch> std::string type_name( tn_identity< L, std::allocator > >, std::string const& suffix ) { std::string tn = sequence_template_name< L, std::allocator > >(); - return tn + '<' + type_name( tn_identity() ) + '>'; + return tn + '<' + type_name( tn_identity(), "" ) + '>' + suffix; } -inline std::string type_name( tn_identity ) +inline std::string type_name( tn_identity, std::string const& suffix ) { - return "std::string"; + return "std::string" + suffix; } -inline std::string type_name( tn_identity ) +inline std::string type_name( tn_identity, std::string const& suffix ) { - return "std::wstring"; + return "std::wstring" + suffix; } #if !defined(BOOST_NO_CXX11_CHAR16_T) -inline std::string type_name( tn_identity ) +inline std::string type_name( tn_identity, std::string const& suffix ) { - return "std::u16string"; + return "std::u16string" + suffix; } #endif #if !defined(BOOST_NO_CXX11_CHAR32_T) -inline std::string type_name( tn_identity ) +inline std::string type_name( tn_identity, std::string const& suffix ) { - return "std::u32string"; + return "std::u32string" + suffix; } #endif #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L -inline std::string type_name( tn_identity> ) +inline std::string type_name( tn_identity>, std::string const& suffix ) { - return "std::u8string"; + return "std::u8string" + suffix; } #endif // string views (et al) -template class L, class Ch> std::string type_name( tn_identity< L > > ) +template class L, class Ch> std::string type_name( tn_identity< L > >, std::string const& suffix ) { std::string tn = sequence_template_name< L > >(); - return tn + '<' + type_name( tn_identity() ) + '>'; + return tn + '<' + type_name( tn_identity(), "" ) + '>' + suffix; } // needed for libstdc++ -inline std::string type_name( tn_identity ) +inline std::string type_name( tn_identity, std::string const& suffix ) { - return "std::ostream"; + return "std::ostream" + suffix; } #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) -inline std::string type_name( tn_identity ) +inline std::string type_name( tn_identity, std::string const& suffix ) { - return "std::string_view"; + return "std::string_view" + suffix; } -inline std::string type_name( tn_identity ) +inline std::string type_name( tn_identity, std::string const& suffix ) { - return "std::wstring_view"; + return "std::wstring_view" + suffix; } #if !defined(BOOST_NO_CXX11_CHAR16_T) -inline std::string type_name( tn_identity ) +inline std::string type_name( tn_identity, std::string const& suffix ) { - return "std::u16string_view"; + return "std::u16string_view" + suffix; } #endif #if !defined(BOOST_NO_CXX11_CHAR32_T) -inline std::string type_name( tn_identity ) +inline std::string type_name( tn_identity, std::string const& suffix ) { - return "std::u32string_view"; + return "std::u32string_view" + suffix; } #endif #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L -inline std::string type_name( tn_identity> ) +inline std::string type_name( tn_identity>, std::string const& suffix ) { - return "std::u8string_view"; + return "std::u8string_view" + suffix; } #endif @@ -597,87 +566,87 @@ inline std::string type_name( tn_identity> ) #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) -template class L, class... T> std::string type_name( tn_identity< L > ) +template class L, class... T> std::string type_name( tn_identity< L >, std::string const& suffix ) { std::string tn = class_template_name< L >(); std::string st = tn_add_each(); - return tn + '<' + st + '>'; + return tn + '<' + st + '>' + suffix; } #else -template class L, class T1> std::string type_name( tn_identity< L > ) +template class L, class T1> std::string type_name( tn_identity< L >, std::string const& suffix ) { std::string tn = class_template_name< L >(); - return tn + '<' + type_name( tn_identity() ) + '>'; + return tn + '<' + type_name( tn_identity(), "" ) + '>' + suffix; } -template class L, class T1, class T2> std::string type_name( tn_identity< L > ) +template class L, class T1, class T2> std::string type_name( tn_identity< L >, std::string const& suffix ) { std::string tn = class_template_name< L >(); - return tn + '<' + type_name( tn_identity() ) + ", " + type_name( tn_identity() ) + '>'; + return tn + '<' + type_name( tn_identity(), "" ) + ", " + type_name( tn_identity(), "" ) + '>' + suffix; } #endif // sequence containers -template class L, class T> std::string type_name( tn_identity< L > > ) +template class L, class T> std::string type_name( tn_identity< L > >, std::string const& suffix ) { std::string tn = sequence_template_name< L > >(); - return tn + '<' + type_name( tn_identity() ) + '>'; + return tn + '<' + type_name( tn_identity(), "" ) + '>' + suffix; } // set -template class L, class T> std::string type_name( tn_identity< L, std::allocator > > ) +template class L, class T> std::string type_name( tn_identity< L, std::allocator > >, std::string const& suffix ) { std::string tn = set_template_name< L, std::allocator > >(); - return tn + '<' + type_name( tn_identity() ) + '>'; + return tn + '<' + type_name( tn_identity(), "" ) + '>' + suffix; } // map -template class L, class T, class U> std::string type_name( tn_identity< L, std::allocator > > > ) +template class L, class T, class U> std::string type_name( tn_identity< L, std::allocator > > >, std::string const& suffix ) { std::string tn = map_template_name< L, std::allocator > > >(); - return tn + '<' + type_name( tn_identity() ) + ", " + type_name( tn_identity() ) + '>'; + return tn + '<' + type_name( tn_identity(), "" ) + ", " + type_name( tn_identity(), "" ) + '>' + suffix; } #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) // unordered_set -template class L, class T> std::string type_name( tn_identity< L, std::equal_to, std::allocator > > ) +template class L, class T> std::string type_name( tn_identity< L, std::equal_to, std::allocator > >, std::string const& suffix ) { std::string tn = set_template_name< L, std::equal_to, std::allocator > >(); - return tn + '<' + type_name( tn_identity() ) + '>'; + return tn + '<' + type_name( tn_identity(), "" ) + '>' + suffix; } // unordered_map -template class L, class T, class U> std::string type_name( tn_identity< L, std::equal_to, std::allocator > > > ) +template class L, class T, class U> std::string type_name( tn_identity< L, std::equal_to, std::allocator > > >, std::string const& suffix ) { std::string tn = map_template_name< L, std::equal_to, std::allocator > > >(); - return tn + '<' + type_name( tn_identity() ) + ", " + type_name( tn_identity() ) + '>'; + return tn + '<' + type_name( tn_identity(), "" ) + ", " + type_name( tn_identity(), "" ) + '>' + suffix; } #endif // array -template class L, class T, std::size_t N> std::string type_name( tn_identity< L > ) +template class L, class T, std::size_t N> std::string type_name( tn_identity< L >, std::string const& suffix ) { std::string tn = array_template_name< L >(); - return tn + '<' + type_name( tn_identity() ) + ", " + tn_to_string( N ) + '>'; + return tn + '<' + type_name( tn_identity(), "" ) + ", " + tn_to_string( N ) + '>' + suffix; } } // namespace detail template std::string type_name() { - return core::detail::type_name( core::detail::tn_identity() ); + return core::detail::type_name( core::detail::tn_identity(), "" ); } } // namespace core diff --git a/test/type_name_test.cpp b/test/type_name_test.cpp index b3439c1..ebd3895 100644 --- a/test/type_name_test.cpp +++ b/test/type_name_test.cpp @@ -111,6 +111,12 @@ int main() TEST(int(float, A, B*)); TEST(void(*)()); + TEST(void(**)()); + TEST(void(***)()); + + TEST(void(* const* const*)()); + TEST(void(* const* const&)()); + TEST(void(&)()); #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) @@ -125,17 +131,29 @@ int main() TEST(A volatile[]); TEST(A const volatile[]); + TEST(A(&)[]); + TEST(A const(***)[]); + TEST(B[1]); TEST(B const[1]); TEST(B volatile[1]); TEST(B const volatile[1]); + TEST(B(&)[1]); + TEST(B const(***)[1]); + TEST(A[][2][3]); TEST(A const[][2][3]); + TEST(A(&)[][2][3]); + TEST(A const(***)[][2][3]); + TEST(B[1][2][3]); TEST(B const volatile[1][2][3]); + TEST(B(&)[1][2][3]); + TEST(B const volatile(***)[1][2][3]); + #if !defined(BOOST_NO_CXX11_NULLPTR) TEST(std::nullptr_t); From b0b48c57835edd00b903830ef187e3af93e1437d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 5 Oct 2021 07:05:34 +0300 Subject: [PATCH 018/258] Support qualified function types --- include/boost/core/type_name.hpp | 131 ++++++++++++++++++++++++++++++- test/type_name_test.cpp | 38 +++++++++ 2 files changed, 168 insertions(+), 1 deletion(-) diff --git a/include/boost/core/type_name.hpp b/include/boost/core/type_name.hpp index d31750b..df13e8e 100644 --- a/include/boost/core/type_name.hpp +++ b/include/boost/core/type_name.hpp @@ -344,7 +344,7 @@ template std::string type_name( tn_identity, std::string const& su #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) -template std::string type_name( tn_identity, std::string const& suffix ) +template std::string function_type_name( tn_identity, std::string const& trailer, std::string const& suffix ) { std::string r = type_name( tn_identity(), "" ); @@ -354,12 +354,141 @@ template std::string type_name( tn_identity, std:: } r += '(' + tn_add_each() + ')'; + r += trailer; return r; } +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), "", suffix ); +} + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), " const", suffix ); +} + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), " volatile", suffix ); +} + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), " const volatile", suffix ); +} + +#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), " &", suffix ); +} + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), " const &", suffix ); +} + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), " volatile &", suffix ); +} + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), " const volatile &", suffix ); +} + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), " &&", suffix ); +} + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), " const &&", suffix ); +} + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), " volatile &&", suffix ); +} + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), " const volatile &&", suffix ); +} + #endif +#if defined( __cpp_noexcept_function_type ) || defined( _NOEXCEPT_TYPES_SUPPORTED ) + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), " noexcept", suffix ); +} + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), " const noexcept", suffix ); +} + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), " volatile noexcept", suffix ); +} + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), " const volatile noexcept", suffix ); +} + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), " & noexcept", suffix ); +} + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), " const & noexcept", suffix ); +} + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), " volatile & noexcept", suffix ); +} + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), " const volatile & noexcept", suffix ); +} + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), " && noexcept", suffix ); +} + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), " const && noexcept", suffix ); +} + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), " volatile && noexcept", suffix ); +} + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), " const volatile && noexcept", suffix ); +} + +#endif + +#endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + // pointers template std::string type_name( tn_identity, std::string const& suffix ) diff --git a/test/type_name_test.cpp b/test/type_name_test.cpp index ebd3895..71a2221 100644 --- a/test/type_name_test.cpp +++ b/test/type_name_test.cpp @@ -124,6 +124,44 @@ int main() TEST(void(&&)()); #endif + + TEST(void() const); + TEST(void() volatile); + TEST(void() const volatile); + +#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) + + TEST(void() &); + TEST(void() const &); + TEST(void() volatile &); + TEST(void() const volatile &); + + TEST(void() &&); + TEST(void() const &&); + TEST(void() volatile &&); + TEST(void() const volatile &&); + +#endif + +#if defined( __cpp_noexcept_function_type ) || defined( _NOEXCEPT_TYPES_SUPPORTED ) + + TEST(void() noexcept); + TEST(void() const noexcept); + TEST(void() volatile noexcept); + TEST(void() const volatile noexcept); + + TEST(void() & noexcept); + TEST(void() const & noexcept); + TEST(void() volatile & noexcept); + TEST(void() const volatile & noexcept); + + TEST(void() && noexcept); + TEST(void() const && noexcept); + TEST(void() volatile && noexcept); + TEST(void() const volatile && noexcept); + +#endif + #endif TEST(A[]); From cd1a8fd238ca8f3960cc5a82e08c293b574d5602 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 5 Oct 2021 07:25:35 +0300 Subject: [PATCH 019/258] Support pointers to members --- include/boost/core/type_name.hpp | 20 +++++++++++++++++++- test/type_name_test.cpp | 22 ++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/include/boost/core/type_name.hpp b/include/boost/core/type_name.hpp index df13e8e..8e332e8 100644 --- a/include/boost/core/type_name.hpp +++ b/include/boost/core/type_name.hpp @@ -350,7 +350,18 @@ template std::string function_type_name( tn_identity() + ')'; @@ -580,6 +591,13 @@ template std::string type_name( tn_identity(), suffix ); } +// pointers to members + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return type_name( tn_identity(), ' ' + type_name( tn_identity(), "" ) + "::*" + suffix ); +} + // nullptr_t #if !defined(BOOST_NO_CXX11_NULLPTR) diff --git a/test/type_name_test.cpp b/test/type_name_test.cpp index 71a2221..437c0c3 100644 --- a/test/type_name_test.cpp +++ b/test/type_name_test.cpp @@ -192,6 +192,28 @@ int main() TEST(B(&)[1][2][3]); TEST(B const volatile(***)[1][2][3]); + TEST(int A::*); + TEST(int const B::*); + + TEST(void(A::*)()); + TEST(void(A::*)() const); + TEST(void(A::*)() volatile); + TEST(void(A::*)() const volatile); + +#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) + + TEST(void(A::*)() &); + TEST(void(A::*)() const &&); + +#endif + +#if defined( __cpp_noexcept_function_type ) || defined( _NOEXCEPT_TYPES_SUPPORTED ) + + TEST(void(A::*)() volatile & noexcept); + TEST(void(A::*)() const volatile && noexcept); + +#endif + #if !defined(BOOST_NO_CXX11_NULLPTR) TEST(std::nullptr_t); From 4f6f7c37991539efb2f2ee3da216f35f4fac65f0 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 5 Oct 2021 07:50:52 +0300 Subject: [PATCH 020/258] Add tests for all fundamental types --- include/boost/core/type_name.hpp | 21 +++++++++++++++++ test/type_name_test.cpp | 40 ++++++++++++++++++++++++++++---- 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/include/boost/core/type_name.hpp b/include/boost/core/type_name.hpp index 8e332e8..d873df1 100644 --- a/include/boost/core/type_name.hpp +++ b/include/boost/core/type_name.hpp @@ -267,6 +267,27 @@ template std::string type_name( tn_identity, std::string const& suff return typeid_name() + suffix; } +// integrals + +inline std::string type_name( tn_identity, std::string const& suffix ) +{ + return "unsigned" + suffix; +} + +#if defined(_MSC_VER) + +inline std::string type_name( tn_identity, std::string const& suffix ) +{ + return "long long" + suffix; +} + +inline std::string type_name( tn_identity, std::string const& suffix ) +{ + return "unsigned long long" + suffix; +} + +#endif + // cv #if !defined(BOOST_MSVC) || BOOST_MSVC >= 1900 diff --git a/test/type_name_test.cpp b/test/type_name_test.cpp index 437c0c3..4c60fda 100644 --- a/test/type_name_test.cpp +++ b/test/type_name_test.cpp @@ -67,7 +67,42 @@ struct Ch int main() { + TEST(signed char); + TEST(unsigned char); + TEST(short); + TEST(unsigned short); TEST(int); + TEST(unsigned); + TEST(long); + TEST(unsigned long); + TEST(long long); + TEST(unsigned long long); + + TEST(char); + TEST(wchar_t); +#if !defined(BOOST_NO_CXX11_CHAR16_T) + TEST(char16_t); +#endif +#if !defined(BOOST_NO_CXX11_CHAR16_T) + TEST(char32_t); +#endif +#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L + TEST(char8_t); +#endif +#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L + TEST(std::byte); +#endif + + TEST(bool); + + TEST(float); + TEST(double); + TEST(long double); + + TEST(void); + TEST(void const); + TEST(void volatile); + TEST(void const volatile); TEST(A); TEST(B); @@ -94,11 +129,6 @@ int main() #endif - TEST(void); - TEST(void const); - TEST(void volatile); - TEST(void const volatile); - TEST(A*); TEST(B const* volatile*); From bb0c6381f640d3a5c74511689dbb9af8d1aba36c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 5 Oct 2021 08:04:01 +0300 Subject: [PATCH 021/258] Add msvc workarounds --- include/boost/core/type_name.hpp | 23 +++++++++++++++++++++++ test/type_name_test.cpp | 14 +++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/include/boost/core/type_name.hpp b/include/boost/core/type_name.hpp index d873df1..c0ec611 100644 --- a/include/boost/core/type_name.hpp +++ b/include/boost/core/type_name.hpp @@ -396,6 +396,8 @@ template std::string type_name( tn_identity, std:: return function_type_name( tn_identity(), "", suffix ); } +#if !defined(BOOST_MSVC) || BOOST_MSVC >= 1900 + template std::string type_name( tn_identity, std::string const& suffix ) { return function_type_name( tn_identity(), " const", suffix ); @@ -411,6 +413,8 @@ template std::string type_name( tn_identity(), " const volatile", suffix ); } +#endif + #if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) template std::string type_name( tn_identity, std::string const& suffix ) @@ -619,6 +623,25 @@ template std::string type_name( tn_identity, std::stri return type_name( tn_identity(), ' ' + type_name( tn_identity(), "" ) + "::*" + suffix ); } +#if defined(BOOST_MSVC) && BOOST_MSVC <= 1900 && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), " const", ' ' + type_name( tn_identity(), "" ) + "::*" + suffix ); +} + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), " volatile", ' ' + type_name( tn_identity(), "" ) + "::*" + suffix ); +} + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), " const volatile", ' ' + type_name( tn_identity(), "" ) + "::*" + suffix ); +} + +#endif + // nullptr_t #if !defined(BOOST_NO_CXX11_NULLPTR) diff --git a/test/type_name_test.cpp b/test/type_name_test.cpp index 4c60fda..e6574cb 100644 --- a/test/type_name_test.cpp +++ b/test/type_name_test.cpp @@ -155,10 +155,14 @@ int main() #endif +#if !defined(BOOST_MSVC) || BOOST_MSVC >= 1900 + TEST(void() const); TEST(void() volatile); TEST(void() const volatile); +#endif + #if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) TEST(void() &); @@ -192,14 +196,16 @@ int main() #endif -#endif +#endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) TEST(A[]); TEST(A const[]); TEST(A volatile[]); TEST(A const volatile[]); +#if !defined(BOOST_MSVC) || BOOST_MSVC >= 1500 TEST(A(&)[]); +#endif TEST(A const(***)[]); TEST(B[1]); @@ -213,7 +219,9 @@ int main() TEST(A[][2][3]); TEST(A const[][2][3]); +#if !defined(BOOST_MSVC) || BOOST_MSVC >= 1500 TEST(A(&)[][2][3]); +#endif TEST(A const(***)[][2][3]); TEST(B[1][2][3]); @@ -225,11 +233,15 @@ int main() TEST(int A::*); TEST(int const B::*); +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + TEST(void(A::*)()); TEST(void(A::*)() const); TEST(void(A::*)() volatile); TEST(void(A::*)() const volatile); +#endif + #if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) TEST(void(A::*)() &); From 1fd2cadddd74823802742e640d78d578142f2708 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 5 Oct 2021 15:38:33 +0300 Subject: [PATCH 022/258] g++ 4.4 has no string::front --- include/boost/core/type_name.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/core/type_name.hpp b/include/boost/core/type_name.hpp index c0ec611..0c622e5 100644 --- a/include/boost/core/type_name.hpp +++ b/include/boost/core/type_name.hpp @@ -373,7 +373,7 @@ template std::string function_type_name( tn_identity Date: Tue, 5 Oct 2021 15:46:22 +0300 Subject: [PATCH 023/258] Add overload for char8_t because Mac has no `typeinfo for char8_t` --- include/boost/core/type_name.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/boost/core/type_name.hpp b/include/boost/core/type_name.hpp index 0c622e5..d8ea942 100644 --- a/include/boost/core/type_name.hpp +++ b/include/boost/core/type_name.hpp @@ -288,6 +288,15 @@ inline std::string type_name( tn_identity, std::string const #endif +#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L + +inline std::string type_name( tn_identity, std::string const& suffix ) +{ + return "char8_t" + suffix; +} + +#endif + // cv #if !defined(BOOST_MSVC) || BOOST_MSVC >= 1900 From 6985b1ae25a51170c52434cefb169f834887aa1d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 5 Oct 2021 15:53:16 +0300 Subject: [PATCH 024/258] Remove extra semicolons --- include/boost/core/type_name.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/core/type_name.hpp b/include/boost/core/type_name.hpp index d8ea942..f155943 100644 --- a/include/boost/core/type_name.hpp +++ b/include/boost/core/type_name.hpp @@ -246,7 +246,7 @@ template int tn_add_each_impl( std::string& st ) if( !st.empty() ) st += ", "; st += type_name( tn_identity(), "" ); return 0; -}; +} template std::string tn_add_each() { @@ -256,7 +256,7 @@ template std::string tn_add_each() (void)A{ 0, tn_add_each_impl( st )... }; return st; -}; +} #endif From 3e9cc2153b4783c75219351131baf770450b849a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 5 Oct 2021 17:11:31 +0300 Subject: [PATCH 025/258] Disable no-rtti tests for g++ 4.4 because breaks --- test/Jamfile.v2 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 63f516f..5f8dc77 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -112,9 +112,9 @@ run-fail lightweight_test_fail4.cpp ; run-fail lightweight_test_fail5.cpp ; run-fail lightweight_test_fail6.cpp ; run-fail lightweight_test_fail7.cpp ; -run-fail lightweight_test_fail7.cpp : : : off : lightweight_test_fail7_no_rtti ; +run-fail lightweight_test_fail7.cpp : : : off gcc-4.4:no : lightweight_test_fail7_no_rtti ; run-fail lightweight_test_fail8.cpp ; -run-fail lightweight_test_fail8.cpp : : : off : lightweight_test_fail8_no_rtti ; +run-fail lightweight_test_fail8.cpp : : : off gcc-4.4:no : lightweight_test_fail8_no_rtti ; run-fail lightweight_test_fail9.cpp ; run-fail lightweight_test_fail10.cpp ; run-fail lightweight_test_fail11.cpp : ; From 87c21a23bb95976848a5a91dda2f917504e422e9 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 5 Oct 2021 17:32:50 +0300 Subject: [PATCH 026/258] Update copyright --- test/Jamfile.v2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 5f8dc77..a55abc2 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -1,6 +1,6 @@ # Boost.Core Library test Jamfile # -# Copyright (c) 2014, 2017 Peter Dimov +# Copyright (c) 2014-2021 Peter Dimov # # Distributed under the Boost Software License, Version 1.0. # See accompanying file LICENSE_1_0.txt or copy at From 75fc48ad32c4ef7055f482a4b34dd00efe0c1b9e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 5 Oct 2021 18:46:47 +0300 Subject: [PATCH 027/258] Add a revision history section to documentation --- doc/changes.qbk | 88 +++++++++++++++++++++++++++++++++++++++++++++++++ doc/core.qbk | 2 ++ 2 files changed, 90 insertions(+) create mode 100644 doc/changes.qbk diff --git a/doc/changes.qbk b/doc/changes.qbk new file mode 100644 index 0000000..f1b877a --- /dev/null +++ b/doc/changes.qbk @@ -0,0 +1,88 @@ +[/ + Copyright 2021 Peter Dimov + Distributed under the Boost Software License, Version 1.0. + https://boost.org/LICENSE_1_0.txt) +] + +[section Revision History] + +[section Changes in 1.78.0] + +* Added a generic implementation to `boost/core/cmath.hpp`, enabled when `BOOST_CORE_USE_GENERIC_CMATH` + is defined or when the platform does not provide the necessary facilities in ``. +* Added `boost::core::type_name`. + +[endsect] + +[section Changes in 1.77.0] + +* `boost/core/uncaught_exceptions.hpp` has been modified for compatibility with Mac OS 10.4 and older. + +[endsect] + +[section Changes in 1.76.0] + +* Add implicit conversion between compatible reference wrappers. +* Add `boost/core/cmath.hpp`, a portable implementation of the floating point classification functions from ``. +* Add `boost/core/bit.hpp`, a portable implementation of the C++20 standard header ``. +* Fix `BOOST_TEST_EQ`, `BOOST_TEST_NE` for character types under C++20. +* Revise allocator access utilities (now support VS2013, and no workarounds use `allocator_traits`.) + +[endsect] + +[section Changes in 1.74.0] + +* Implemented the allocator access utilities which provide a replacement for `allocator_traits` + with individual traits and functions for each facility. They support the C++11 allocator model + when possible and provide a fallback for C++98 compatibility. + +[endsect] + +[section Changes in 1.71.0] + +* Added functions `alloc_construct`, `alloc_construct_n`, `alloc_destroy`, and `alloc_destroy_n` + in `` for allocator aware and exception safe construction and + destruction of objects and arrays. +* Added constexpr functions `first_scalar` in `` for obtaining a pointer + to the first scalar element of an array. Given a pointer of type `T*` they return a pointer of type + `remove_all_extents_t*`. +* Added class template `noinit_adaptor` in `` which is an allocator adaptor + that converts any allocator into one whose `construct(ptr)` performs default initialization via placement + `new`, and whose `destroy(ptr)` invokes the `value_type` destructor directly. +* Added class template `default_allocator` in ``, which can serve as a minimal + default allocator that has interface similar to C++20 `std::allocator`, supports configurations with disabled + exceptions and does not have `std` as an associated namespace. The allocator uses `operator new` and + `operator delete` for allocation. +* In `` header, added workarounds for better compatibility with QNX SDP 7.0 + when libc++/libc++abi libraries are used. +* The `` header is now marked as deprecated and will be removed in a future release. + `` should be used instead. + +[endsect] + +[section Changes in 1.69.0] + +* Implemented `boost::empty_value`, for library authors to conveniently leverage the Empty Base Optimization to + store objects of potentially empty types. +* Implemented `boost::quick_exit` to provide the C++11 standard library facility `std::quick_exit` functionality. +* Reduced the number of statics in Lightweight Test, and employ lighter abort behavior for MSVC compilers upon + failure to call `boost::report_errors`. + +[endsect] + +[section Changes in 1.67.0] + +* Updated `to_address` and `pointer_traits` to reflect the design adopted for C++20 in + [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0653r2.html P0653R2]. + +[endsect] + +[section Changes in 1.65.0] + +* Implemented `pointer_traits` for C++03 and higher, that implements + [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0653r0.html P0653r0]. +* Added `BOOST_TEST_GT` and `BOOST_TEST_GE` to Lightweight Test. + +[endsect] + +[endsect] diff --git a/doc/core.qbk b/doc/core.qbk index 9c20459..17538fe 100644 --- a/doc/core.qbk +++ b/doc/core.qbk @@ -38,6 +38,8 @@ criteria for inclusion is that the utility component be: [endsect] +[include changes.qbk] + [include addressof.qbk] [include allocator_access.qbk] [include alloc_construct.qbk] From 531726eb09333000807cdb232111efbb7c067acd Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 5 Oct 2021 19:05:40 +0300 Subject: [PATCH 028/258] Update msvc workarounds in type_name_test --- test/type_name_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/type_name_test.cpp b/test/type_name_test.cpp index e6574cb..6b61def 100644 --- a/test/type_name_test.cpp +++ b/test/type_name_test.cpp @@ -203,7 +203,7 @@ int main() TEST(A volatile[]); TEST(A const volatile[]); -#if !defined(BOOST_MSVC) || BOOST_MSVC >= 1500 +#if !defined(BOOST_MSVC) || BOOST_MSVC >= 1700 TEST(A(&)[]); #endif TEST(A const(***)[]); @@ -219,7 +219,7 @@ int main() TEST(A[][2][3]); TEST(A const[][2][3]); -#if !defined(BOOST_MSVC) || BOOST_MSVC >= 1500 +#if !defined(BOOST_MSVC) || BOOST_MSVC >= 1700 TEST(A(&)[][2][3]); #endif TEST(A const(***)[][2][3]); From 3ec157eb6fe51cf6802b055e070644b555154352 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 5 Oct 2021 19:16:24 +0300 Subject: [PATCH 029/258] Disable cmath_test_generic on msvc-8.0 --- test/Jamfile.v2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 63f516f..dd9fc10 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -232,7 +232,7 @@ run no_exceptions_support_test.cpp ; run no_exceptions_support_test.cpp : : : off : no_exceptions_support_test_nx ; run cmath_test.cpp ; -run cmath_test.cpp : : : BOOST_CORE_USE_GENERIC_CMATH : cmath_test_generic ; +run cmath_test.cpp : : : BOOST_CORE_USE_GENERIC_CMATH msvc-8.0:no : cmath_test_generic ; run bit_cast_test.cpp ; run bit_rotate_test.cpp ; From 0deaa2d502884c334193a4277d7b7d59de66af5e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 5 Oct 2021 19:22:20 +0300 Subject: [PATCH 030/258] Update msvc-12.0 workaround --- include/boost/core/type_name.hpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/boost/core/type_name.hpp b/include/boost/core/type_name.hpp index f155943..5512c0c 100644 --- a/include/boost/core/type_name.hpp +++ b/include/boost/core/type_name.hpp @@ -632,7 +632,12 @@ template std::string type_name( tn_identity, std::stri return type_name( tn_identity(), ' ' + type_name( tn_identity(), "" ) + "::*" + suffix ); } -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1900 && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#if defined(BOOST_MSVC) && BOOST_MSVC < 1900 && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +template std::string type_name( tn_identity, std::string const& suffix ) +{ + return function_type_name( tn_identity(), "", ' ' + type_name( tn_identity(), "" ) + "::*" + suffix ); +} template std::string type_name( tn_identity, std::string const& suffix ) { From 93c18fb9370f8e3fc375029444e36aa15392b3ef Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 6 Oct 2021 03:36:40 +0300 Subject: [PATCH 031/258] Use BOOST_TEST_TRAIT_SAME in sv_types_test --- test/sv_types_test.cpp | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/test/sv_types_test.cpp b/test/sv_types_test.cpp index 184a49f..9f2592a 100644 --- a/test/sv_types_test.cpp +++ b/test/sv_types_test.cpp @@ -14,35 +14,33 @@ struct Ch int main() { - using boost::core::is_same; - typedef boost::core::basic_string_view ch_string_view; - BOOST_TEST_TRAIT_TRUE((is_same< ch_string_view::traits_type, std::char_traits >)); - BOOST_TEST_TRAIT_TRUE((is_same< ch_string_view::value_type, Ch >)); - BOOST_TEST_TRAIT_TRUE((is_same< ch_string_view::pointer, Ch* >)); - BOOST_TEST_TRAIT_TRUE((is_same< ch_string_view::const_pointer, Ch const* >)); - BOOST_TEST_TRAIT_TRUE((is_same< ch_string_view::reference, Ch& >)); - BOOST_TEST_TRAIT_TRUE((is_same< ch_string_view::const_reference, Ch const& >)); - BOOST_TEST_TRAIT_TRUE((is_same< ch_string_view::iterator, ch_string_view::const_iterator >)); - BOOST_TEST_TRAIT_TRUE((is_same< std::iterator_traits::iterator_category, std::random_access_iterator_tag >)); - BOOST_TEST_TRAIT_TRUE((is_same< ch_string_view::reverse_iterator, ch_string_view::const_reverse_iterator >)); - BOOST_TEST_TRAIT_TRUE((is_same< ch_string_view::reverse_iterator, std::reverse_iterator >)); - BOOST_TEST_TRAIT_TRUE((is_same< ch_string_view::size_type, std::size_t >)); - BOOST_TEST_TRAIT_TRUE((is_same< ch_string_view::difference_type, std::ptrdiff_t >)); + BOOST_TEST_TRAIT_SAME(ch_string_view::traits_type, std::char_traits); + BOOST_TEST_TRAIT_SAME(ch_string_view::value_type, Ch); + BOOST_TEST_TRAIT_SAME(ch_string_view::pointer, Ch*); + BOOST_TEST_TRAIT_SAME(ch_string_view::const_pointer, Ch const*); + BOOST_TEST_TRAIT_SAME(ch_string_view::reference, Ch&); + BOOST_TEST_TRAIT_SAME(ch_string_view::const_reference, Ch const&); + BOOST_TEST_TRAIT_SAME(ch_string_view::iterator, ch_string_view::const_iterator); + BOOST_TEST_TRAIT_SAME(std::iterator_traits::iterator_category, std::random_access_iterator_tag); + BOOST_TEST_TRAIT_SAME(ch_string_view::reverse_iterator, ch_string_view::const_reverse_iterator); + BOOST_TEST_TRAIT_SAME(ch_string_view::reverse_iterator, std::reverse_iterator); + BOOST_TEST_TRAIT_SAME(ch_string_view::size_type, std::size_t); + BOOST_TEST_TRAIT_SAME(ch_string_view::difference_type, std::ptrdiff_t); BOOST_TEST_EQ(ch_string_view::npos, static_cast(-1)); - BOOST_TEST_TRAIT_TRUE((is_same< boost::core::string_view, boost::core::basic_string_view >)); - BOOST_TEST_TRAIT_TRUE((is_same< boost::core::wstring_view, boost::core::basic_string_view >)); + BOOST_TEST_TRAIT_SAME(boost::core::string_view, boost::core::basic_string_view); + BOOST_TEST_TRAIT_SAME(boost::core::wstring_view, boost::core::basic_string_view); #if !defined(BOOST_NO_CXX11_CHAR16_T) - BOOST_TEST_TRAIT_TRUE((is_same< boost::core::u16string_view, boost::core::basic_string_view >)); + BOOST_TEST_TRAIT_SAME(boost::core::u16string_view, boost::core::basic_string_view); #endif #if !defined(BOOST_NO_CXX11_CHAR32_T) - BOOST_TEST_TRAIT_TRUE((is_same< boost::core::u32string_view, boost::core::basic_string_view >)); + BOOST_TEST_TRAIT_SAME(boost::core::u32string_view, boost::core::basic_string_view); #endif #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L - BOOST_TEST_TRAIT_TRUE((is_same< boost::core::u8string_view, boost::core::basic_string_view >)); + BOOST_TEST_TRAIT_SAME(boost::core::u8string_view, boost::core::basic_string_view); #endif return boost::report_errors(); From c7dfa29f297d2b09f1a7c9c17d63f6030f094a11 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 6 Oct 2021 04:35:37 +0300 Subject: [PATCH 032/258] Add sv_starts_with_test --- include/boost/core/string_view.hpp | 12 +++++++ test/Jamfile.v2 | 1 + test/sv_starts_with_test.cpp | 50 ++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 test/sv_starts_with_test.cpp diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index ae71d72..3117e7d 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -563,6 +563,18 @@ public: { return find( s ) != npos; } + + // relational operators + + BOOST_CONSTEXPR friend bool operator==( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) == 0; + } + + BOOST_CONSTEXPR friend bool operator!=( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) != 0; + } }; #if defined(BOOST_NO_CXX17_INLINE_VARIABLES) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index f174ba2..fb6d452 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -254,6 +254,7 @@ run sv_modifiers_test.cpp ; run sv_copy_test.cpp ; run sv_substr_test.cpp ; run sv_compare_test.cpp ; +run sv_starts_with_test.cpp ; use-project /boost/core/swap : ./swap ; build-project ./swap ; diff --git a/test/sv_starts_with_test.cpp b/test/sv_starts_with_test.cpp new file mode 100644 index 0000000..e3d69c5 --- /dev/null +++ b/test/sv_starts_with_test.cpp @@ -0,0 +1,50 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +int main() +{ + { + boost::core::string_view sv( "" ); + + BOOST_TEST( sv.starts_with( boost::core::string_view() ) ); + BOOST_TEST( sv.starts_with( boost::core::string_view( "" ) ) ); + BOOST_TEST( sv.starts_with( "" ) ); + + BOOST_TEST( !sv.starts_with( boost::core::string_view( "1" ) ) ); + BOOST_TEST( !sv.starts_with( '1' ) ); + BOOST_TEST( !sv.starts_with( "1" ) ); + } + + { + boost::core::string_view sv( "123" ); + + BOOST_TEST( sv.starts_with( boost::core::string_view() ) ); + BOOST_TEST( sv.starts_with( boost::core::string_view( "" ) ) ); + BOOST_TEST( sv.starts_with( "" ) ); + + BOOST_TEST( sv.starts_with( boost::core::string_view( "1" ) ) ); + BOOST_TEST( sv.starts_with( '1' ) ); + BOOST_TEST( sv.starts_with( "1" ) ); + + BOOST_TEST( sv.starts_with( boost::core::string_view( "12" ) ) ); + BOOST_TEST( sv.starts_with( "12" ) ); + + BOOST_TEST( sv.starts_with( boost::core::string_view( "123" ) ) ); + BOOST_TEST( sv.starts_with( "123" ) ); + + BOOST_TEST( !sv.starts_with( boost::core::string_view( "1234" ) ) ); + BOOST_TEST( !sv.starts_with( "1234" ) ); + + BOOST_TEST( !sv.starts_with( boost::core::string_view( "2" ) ) ); + BOOST_TEST( !sv.starts_with( '2' ) ); + BOOST_TEST( !sv.starts_with( "2" ) ); + } + + return boost::report_errors(); +} From f9fa1772f2e2cc82f4efcdffad917c608fd70eb9 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 6 Oct 2021 04:39:16 +0300 Subject: [PATCH 033/258] Add sv_ends_with_test --- test/Jamfile.v2 | 1 + test/sv_ends_with_test.cpp | 50 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 test/sv_ends_with_test.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index fb6d452..bb41d02 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -255,6 +255,7 @@ run sv_copy_test.cpp ; run sv_substr_test.cpp ; run sv_compare_test.cpp ; run sv_starts_with_test.cpp ; +run sv_ends_with_test.cpp ; use-project /boost/core/swap : ./swap ; build-project ./swap ; diff --git a/test/sv_ends_with_test.cpp b/test/sv_ends_with_test.cpp new file mode 100644 index 0000000..6c037ef --- /dev/null +++ b/test/sv_ends_with_test.cpp @@ -0,0 +1,50 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +int main() +{ + { + boost::core::string_view sv( "" ); + + BOOST_TEST( sv.ends_with( boost::core::string_view() ) ); + BOOST_TEST( sv.ends_with( boost::core::string_view( "" ) ) ); + BOOST_TEST( sv.ends_with( "" ) ); + + BOOST_TEST( !sv.ends_with( boost::core::string_view( "1" ) ) ); + BOOST_TEST( !sv.ends_with( '1' ) ); + BOOST_TEST( !sv.ends_with( "1" ) ); + } + + { + boost::core::string_view sv( "123" ); + + BOOST_TEST( sv.ends_with( boost::core::string_view() ) ); + BOOST_TEST( sv.ends_with( boost::core::string_view( "" ) ) ); + BOOST_TEST( sv.ends_with( "" ) ); + + BOOST_TEST( sv.ends_with( boost::core::string_view( "3" ) ) ); + BOOST_TEST( sv.ends_with( '3' ) ); + BOOST_TEST( sv.ends_with( "3" ) ); + + BOOST_TEST( sv.ends_with( boost::core::string_view( "23" ) ) ); + BOOST_TEST( sv.ends_with( "23" ) ); + + BOOST_TEST( sv.ends_with( boost::core::string_view( "123" ) ) ); + BOOST_TEST( sv.ends_with( "123" ) ); + + BOOST_TEST( !sv.ends_with( boost::core::string_view( "1234" ) ) ); + BOOST_TEST( !sv.ends_with( "1234" ) ); + + BOOST_TEST( !sv.ends_with( boost::core::string_view( "2" ) ) ); + BOOST_TEST( !sv.ends_with( '2' ) ); + BOOST_TEST( !sv.ends_with( "2" ) ); + } + + return boost::report_errors(); +} From 09044f58d6f640f610e99597faaa4da35ccb92a3 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 6 Oct 2021 04:58:36 +0300 Subject: [PATCH 034/258] Add sv_find_test --- include/boost/core/string_view.hpp | 2 +- test/Jamfile.v2 | 1 + test/sv_find_test.cpp | 130 +++++++++++++++++++++++++++++ 3 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 test/sv_find_test.cpp diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index 3117e7d..e9f9059 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -351,7 +351,7 @@ public: p = traits_type::find( p, last - p, s[0] ); if( p == 0 ) break; - if( last - p < n ) break; + if( static_cast( last - p ) < n ) break; if( traits_type::compare( p, s, n ) == 0 ) return p - data(); diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index bb41d02..89d40ac 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -256,6 +256,7 @@ run sv_substr_test.cpp ; run sv_compare_test.cpp ; run sv_starts_with_test.cpp ; run sv_ends_with_test.cpp ; +run sv_find_test.cpp ; use-project /boost/core/swap : ./swap ; build-project ./swap ; diff --git a/test/sv_find_test.cpp b/test/sv_find_test.cpp new file mode 100644 index 0000000..537c975 --- /dev/null +++ b/test/sv_find_test.cpp @@ -0,0 +1,130 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include + +int main() +{ + std::size_t const npos = boost::core::string_view::npos; + + { + boost::core::string_view sv( "" ); + + BOOST_TEST_EQ( sv.find( boost::core::string_view() ), 0 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view(), 1 ), npos ); + + BOOST_TEST_EQ( sv.find( boost::core::string_view( "" ) ), 0 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find( boost::core::string_view( "1" ) ), npos ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "1" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find( '1' ), npos ); + BOOST_TEST_EQ( sv.find( '1', 1 ), npos ); + + BOOST_TEST_EQ( sv.find( "" ), 0 ); + BOOST_TEST_EQ( sv.find( "", 1 ), npos ); + + BOOST_TEST_EQ( sv.find( "1" ), npos ); + BOOST_TEST_EQ( sv.find( "1", 1 ), npos ); + + BOOST_TEST_EQ( sv.find( "1", 0, 0 ), 0 ); + BOOST_TEST_EQ( sv.find( "1", 1, 0 ), npos ); + + BOOST_TEST_EQ( sv.find( "1", 0, 1 ), npos ); + BOOST_TEST_EQ( sv.find( "1", 1, 1 ), npos ); + } + + { + boost::core::string_view sv( "123123" ); + + BOOST_TEST_EQ( sv.find( boost::core::string_view() ), 0 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view(), 1 ), 1 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view(), 6 ), 6 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view(), 7 ), npos ); + + BOOST_TEST_EQ( sv.find( boost::core::string_view( "" ) ), 0 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "" ), 6 ), 6 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find( boost::core::string_view( "1" ) ), 0 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "1" ), 1 ), 3 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "1" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "1" ), 4 ), npos ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "1" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "1" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find( boost::core::string_view( "23" ) ), 1 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "23" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "23" ), 2 ), 4 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "23" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "23" ), 5 ), npos ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "23" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "23" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find( '1' ), 0 ); + BOOST_TEST_EQ( sv.find( '1', 1 ), 3 ); + BOOST_TEST_EQ( sv.find( '1', 2 ), 3 ); + BOOST_TEST_EQ( sv.find( '1', 3 ), 3 ); + BOOST_TEST_EQ( sv.find( '1', 4 ), npos ); + BOOST_TEST_EQ( sv.find( '1', 5 ), npos ); + BOOST_TEST_EQ( sv.find( '1', 6 ), npos ); + BOOST_TEST_EQ( sv.find( '1', 7 ), npos ); + + BOOST_TEST_EQ( sv.find( '3' ), 2 ); + BOOST_TEST_EQ( sv.find( '3', 1 ), 2 ); + BOOST_TEST_EQ( sv.find( '3', 2 ), 2 ); + BOOST_TEST_EQ( sv.find( '3', 3 ), 5 ); + BOOST_TEST_EQ( sv.find( '3', 4 ), 5 ); + BOOST_TEST_EQ( sv.find( '3', 5 ), 5 ); + BOOST_TEST_EQ( sv.find( '3', 6 ), npos ); + BOOST_TEST_EQ( sv.find( '3', 7 ), npos ); + + BOOST_TEST_EQ( sv.find( '9' ), npos ); + + BOOST_TEST_EQ( sv.find( "" ), 0 ); + BOOST_TEST_EQ( sv.find( "", 1 ), 1 ); + BOOST_TEST_EQ( sv.find( "", 6 ), 6 ); + BOOST_TEST_EQ( sv.find( "", 7 ), npos ); + + BOOST_TEST_EQ( sv.find( "1" ), 0 ); + BOOST_TEST_EQ( sv.find( "1", 1 ), 3 ); + BOOST_TEST_EQ( sv.find( "1", 3 ), 3 ); + BOOST_TEST_EQ( sv.find( "1", 4 ), npos ); + BOOST_TEST_EQ( sv.find( "1", 6 ), npos ); + BOOST_TEST_EQ( sv.find( "1", 7 ), npos ); + + BOOST_TEST_EQ( sv.find( "23" ), 1 ); + BOOST_TEST_EQ( sv.find( "23", 1 ), 1 ); + BOOST_TEST_EQ( sv.find( "23", 2 ), 4 ); + BOOST_TEST_EQ( sv.find( "23", 4 ), 4 ); + BOOST_TEST_EQ( sv.find( "23", 5 ), npos ); + BOOST_TEST_EQ( sv.find( "23", 6 ), npos ); + BOOST_TEST_EQ( sv.find( "23", 7 ), npos ); + + BOOST_TEST_EQ( sv.find( "123", 0, 0 ), 0 ); + BOOST_TEST_EQ( sv.find( "123", 1, 0 ), 1 ); + BOOST_TEST_EQ( sv.find( "123", 6, 0 ), 6 ); + BOOST_TEST_EQ( sv.find( "123", 7, 0 ), npos ); + + BOOST_TEST_EQ( sv.find( "123", 0, 1 ), 0 ); + BOOST_TEST_EQ( sv.find( "123", 1, 1 ), 3 ); + BOOST_TEST_EQ( sv.find( "123", 3, 1 ), 3 ); + BOOST_TEST_EQ( sv.find( "123", 4, 1 ), npos ); + BOOST_TEST_EQ( sv.find( "123", 6, 1 ), npos ); + BOOST_TEST_EQ( sv.find( "123", 7, 1 ), npos ); + + BOOST_TEST_EQ( sv.find( "123", 0, 3 ), 0 ); + BOOST_TEST_EQ( sv.find( "123", 1, 3 ), 3 ); + BOOST_TEST_EQ( sv.find( "123", 3, 3 ), 3 ); + BOOST_TEST_EQ( sv.find( "123", 4, 3 ), npos ); + BOOST_TEST_EQ( sv.find( "123", 6, 3 ), npos ); + BOOST_TEST_EQ( sv.find( "123", 7, 3 ), npos ); + } + + return boost::report_errors(); +} From a8e7a3395e2a493ce42496ecf8d32fcd8031f37b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 6 Oct 2021 05:36:12 +0300 Subject: [PATCH 035/258] Add sv_iteration_test --- include/boost/core/string_view.hpp | 8 ++-- test/Jamfile.v2 | 1 + test/sv_construct_test.cpp | 72 +++++++++++++++--------------- test/sv_iteration_test.cpp | 61 +++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 40 deletions(-) create mode 100644 test/sv_iteration_test.cpp diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index e9f9059..818c90d 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -122,22 +122,22 @@ public: BOOST_CONSTEXPR const_reverse_iterator rbegin() const BOOST_NOEXCEPT { - return const_reverse_iterator( begin() ); + return const_reverse_iterator( end() ); } BOOST_CONSTEXPR const_reverse_iterator rend() const BOOST_NOEXCEPT { - return const_reverse_iterator( end() ); + return const_reverse_iterator( begin() ); } BOOST_CONSTEXPR const_reverse_iterator crbegin() const BOOST_NOEXCEPT { - return const_reverse_iterator( begin() ); + return const_reverse_iterator( end() ); } BOOST_CONSTEXPR const_reverse_iterator crend() const BOOST_NOEXCEPT { - return const_reverse_iterator( end() ); + return const_reverse_iterator( begin() ); } // capacity diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 89d40ac..3a8f892 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -249,6 +249,7 @@ run type_name_test.cpp ; run sv_types_test.cpp ; run sv_construct_test.cpp ; +run sv_iteration_test.cpp ; run sv_element_access_test.cpp ; run sv_modifiers_test.cpp ; run sv_copy_test.cpp ; diff --git a/test/sv_construct_test.cpp b/test/sv_construct_test.cpp index af38943..3e7343d 100644 --- a/test/sv_construct_test.cpp +++ b/test/sv_construct_test.cpp @@ -29,11 +29,11 @@ int main() BOOST_TEST_EQ( sv.cbegin(), sv.data() ); BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); - BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.begin() ) ); - BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.begin() ) ); - BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cbegin() ) ); - BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cbegin() ) ); BOOST_TEST_EQ( sv.length(), sv.size() ); BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); @@ -55,11 +55,11 @@ int main() BOOST_TEST_EQ( sv.cbegin(), sv.data() ); BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); - BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.begin() ) ); - BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.begin() ) ); - BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cbegin() ) ); - BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cbegin() ) ); BOOST_TEST_EQ( sv.length(), sv.size() ); BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); @@ -87,11 +87,11 @@ int main() BOOST_TEST_EQ( sv.cbegin(), sv.data() ); BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); - BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.begin() ) ); - BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.begin() ) ); - BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cbegin() ) ); - BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cbegin() ) ); BOOST_TEST_EQ( sv.length(), sv.size() ); BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); @@ -119,11 +119,11 @@ int main() BOOST_TEST_EQ( sv.cbegin(), sv.data() ); BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); - BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.begin() ) ); - BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.begin() ) ); - BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cbegin() ) ); - BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cbegin() ) ); BOOST_TEST_EQ( sv.length(), sv.size() ); BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); @@ -151,11 +151,11 @@ int main() BOOST_TEST_EQ( sv.cbegin(), sv.data() ); BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); - BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.begin() ) ); - BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.begin() ) ); - BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cbegin() ) ); - BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cbegin() ) ); BOOST_TEST_EQ( sv.length(), sv.size() ); BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); @@ -183,11 +183,11 @@ int main() BOOST_TEST_EQ( sv.cbegin(), sv.data() ); BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); - BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.begin() ) ); - BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.begin() ) ); - BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cbegin() ) ); - BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cbegin() ) ); BOOST_TEST_EQ( sv.length(), sv.size() ); BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); @@ -215,11 +215,11 @@ int main() BOOST_TEST_EQ( sv.cbegin(), sv.data() ); BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); - BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.begin() ) ); - BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.begin() ) ); - BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cbegin() ) ); - BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cbegin() ) ); BOOST_TEST_EQ( sv.length(), sv.size() ); BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); @@ -247,11 +247,11 @@ int main() BOOST_TEST_EQ( sv.cbegin(), sv.data() ); BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); - BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.begin() ) ); - BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.begin() ) ); - BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cbegin() ) ); - BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cbegin() ) ); BOOST_TEST_EQ( sv.length(), sv.size() ); BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); @@ -281,11 +281,11 @@ int main() BOOST_TEST_EQ( sv.cbegin(), sv.data() ); BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); - BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.begin() ) ); - BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.begin() ) ); - BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cbegin() ) ); - BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cbegin() ) ); BOOST_TEST_EQ( sv.length(), sv.size() ); BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); diff --git a/test/sv_iteration_test.cpp b/test/sv_iteration_test.cpp new file mode 100644 index 0000000..7e85dc0 --- /dev/null +++ b/test/sv_iteration_test.cpp @@ -0,0 +1,61 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +int main() +{ + { + boost::core::string_view sv; + + { + std::string s( sv.begin(), sv.end() ); + BOOST_TEST_EQ( s, std::string( "" ) ); + } + + { + std::string s( sv.cbegin(), sv.cend() ); + BOOST_TEST_EQ( s, std::string( "" ) ); + } + + { + std::string s( sv.rbegin(), sv.rend() ); + BOOST_TEST_EQ( s, std::string( "" ) ); + } + + { + std::string s( sv.crbegin(), sv.crend() ); + BOOST_TEST_EQ( s, std::string( "" ) ); + } + } + + { + boost::core::string_view sv( "123" ); + + { + std::string s( sv.begin(), sv.end() ); + BOOST_TEST_EQ( s, std::string( "123" ) ); + } + + { + std::string s( sv.cbegin(), sv.cend() ); + BOOST_TEST_EQ( s, std::string( "123" ) ); + } + + { + std::string s( sv.rbegin(), sv.rend() ); + BOOST_TEST_EQ( s, std::string( "321" ) ); + } + + { + std::string s( sv.crbegin(), sv.crend() ); + BOOST_TEST_EQ( s, std::string( "321" ) ); + } + } + + return boost::report_errors(); +} From 673e3c302c2d447e2191bdec1efc3980bedbbc18 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 6 Oct 2021 05:49:09 +0300 Subject: [PATCH 036/258] Add sv_rfind_test --- include/boost/core/string_view.hpp | 15 ++- test/Jamfile.v2 | 1 + test/sv_rfind_test.cpp | 169 +++++++++++++++++++++++++++++ 3 files changed, 181 insertions(+), 4 deletions(-) create mode 100644 test/sv_rfind_test.cpp diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index 818c90d..743443f 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -375,13 +375,20 @@ public: BOOST_CXX14_CONSTEXPR size_type rfind( Ch c, size_type pos = npos ) const BOOST_NOEXCEPT { - if( pos > size() ) + size_type n = size(); + + if( n == 0 ) { - pos = size(); + return npos; } - const_reverse_iterator r = std::find( rbegin() + pos, rend(), c ); - return r == rend()? npos: size() - 1 - ( r - rbegin() ); + if( pos > n - 1 ) + { + pos = n - 1; + } + + const_reverse_iterator r = std::find( rbegin() + n - 1 - pos, rend(), c ); + return r == rend()? npos: n - 1 - ( r - rbegin() ); } BOOST_CXX14_CONSTEXPR size_type rfind( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 3a8f892..11bbea6 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -258,6 +258,7 @@ run sv_compare_test.cpp ; run sv_starts_with_test.cpp ; run sv_ends_with_test.cpp ; run sv_find_test.cpp ; +run sv_rfind_test.cpp ; use-project /boost/core/swap : ./swap ; build-project ./swap ; diff --git a/test/sv_rfind_test.cpp b/test/sv_rfind_test.cpp new file mode 100644 index 0000000..65a0ee8 --- /dev/null +++ b/test/sv_rfind_test.cpp @@ -0,0 +1,169 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include + +int main() +{ + std::size_t const npos = boost::core::string_view::npos; + + { + boost::core::string_view sv( "" ); + + BOOST_TEST_EQ( sv.rfind( boost::core::string_view() ), 0 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view(), 1 ), 0 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view(), 0 ), 0 ); + + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "" ) ), 0 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "" ), 1 ), 0 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "" ), 0 ), 0 ); + + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "1" ) ), npos ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "1" ), 1 ), npos ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "1" ), 0 ), npos ); + + BOOST_TEST_EQ( sv.rfind( '1' ), npos ); + BOOST_TEST_EQ( sv.rfind( '1', 1 ), npos ); + BOOST_TEST_EQ( sv.rfind( '1', 0 ), npos ); + + BOOST_TEST_EQ( sv.rfind( "" ), 0 ); + BOOST_TEST_EQ( sv.rfind( "", 1 ), 0 ); + BOOST_TEST_EQ( sv.rfind( "", 0 ), 0 ); + + BOOST_TEST_EQ( sv.rfind( "1" ), npos ); + BOOST_TEST_EQ( sv.rfind( "1", 1 ), npos ); + BOOST_TEST_EQ( sv.rfind( "1", 0 ), npos ); + + BOOST_TEST_EQ( sv.rfind( "1", npos, 0 ), 0 ); + BOOST_TEST_EQ( sv.rfind( "1", 1, 0 ), 0 ); + BOOST_TEST_EQ( sv.rfind( "1", 0, 0 ), 0 ); + + BOOST_TEST_EQ( sv.rfind( "1", npos, 1 ), npos ); + BOOST_TEST_EQ( sv.rfind( "1", 1, 1 ), npos ); + BOOST_TEST_EQ( sv.rfind( "1", 0, 1 ), npos ); + } + + { + boost::core::string_view sv( "123123" ); + + BOOST_TEST_EQ( sv.rfind( boost::core::string_view() ), 6 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view(), 7 ), 6 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view(), 6 ), 6 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view(), 5 ), 5 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view(), 1 ), 1 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view(), 0 ), 0 ); + + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "" ) ), 6 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "" ), 7 ), 6 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "" ), 6 ), 6 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "" ), 0 ), 0 ); + + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "1" ) ), 3 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "1" ), 7 ), 3 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "1" ), 6 ), 3 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "1" ), 5 ), 3 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "1" ), 4 ), 3 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "1" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "1" ), 2 ), 0 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "1" ), 1 ), 0 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "1" ), 0 ), 0 ); + + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "23" ) ), 4 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "23" ), 7 ), 4 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "23" ), 6 ), 4 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "23" ), 5 ), 4 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "23" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "23" ), 3 ), 1 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "23" ), 2 ), 1 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "23" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "23" ), 0 ), npos ); + + BOOST_TEST_EQ( sv.rfind( '1' ), 3 ); + BOOST_TEST_EQ( sv.rfind( '1', 7 ), 3 ); + BOOST_TEST_EQ( sv.rfind( '1', 6 ), 3 ); + BOOST_TEST_EQ( sv.rfind( '1', 5 ), 3 ); + BOOST_TEST_EQ( sv.rfind( '1', 4 ), 3 ); + BOOST_TEST_EQ( sv.rfind( '1', 3 ), 3 ); + BOOST_TEST_EQ( sv.rfind( '1', 2 ), 0 ); + BOOST_TEST_EQ( sv.rfind( '1', 1 ), 0 ); + BOOST_TEST_EQ( sv.rfind( '1', 0 ), 0 ); + + BOOST_TEST_EQ( sv.rfind( '3' ), 5 ); + BOOST_TEST_EQ( sv.rfind( '3', 7 ), 5 ); + BOOST_TEST_EQ( sv.rfind( '3', 6 ), 5 ); + BOOST_TEST_EQ( sv.rfind( '3', 5 ), 5 ); + BOOST_TEST_EQ( sv.rfind( '3', 4 ), 2 ); + BOOST_TEST_EQ( sv.rfind( '3', 3 ), 2 ); + BOOST_TEST_EQ( sv.rfind( '3', 2 ), 2 ); + BOOST_TEST_EQ( sv.rfind( '3', 1 ), npos ); + BOOST_TEST_EQ( sv.rfind( '3', 0 ), npos ); + + BOOST_TEST_EQ( sv.rfind( '9' ), npos ); + BOOST_TEST_EQ( sv.rfind( '9', 7 ), npos ); + BOOST_TEST_EQ( sv.rfind( '9', 6 ), npos ); + + BOOST_TEST_EQ( sv.rfind( "" ), 6 ); + BOOST_TEST_EQ( sv.rfind( "", 7 ), 6 ); + BOOST_TEST_EQ( sv.rfind( "", 6 ), 6 ); + BOOST_TEST_EQ( sv.rfind( "", 5 ), 5 ); + BOOST_TEST_EQ( sv.rfind( "", 1 ), 1 ); + BOOST_TEST_EQ( sv.rfind( "", 0 ), 0 ); + + BOOST_TEST_EQ( sv.rfind( "1" ), 3 ); + BOOST_TEST_EQ( sv.rfind( "1", 7 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "1", 6 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "1", 5 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "1", 4 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "1", 3 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "1", 2 ), 0 ); + BOOST_TEST_EQ( sv.rfind( "1", 1 ), 0 ); + BOOST_TEST_EQ( sv.rfind( "1", 0 ), 0 ); + + BOOST_TEST_EQ( sv.rfind( "23" ), 4 ); + BOOST_TEST_EQ( sv.rfind( "23", 7 ), 4 ); + BOOST_TEST_EQ( sv.rfind( "23", 6 ), 4 ); + BOOST_TEST_EQ( sv.rfind( "23", 5 ), 4 ); + BOOST_TEST_EQ( sv.rfind( "23", 4 ), 4 ); + BOOST_TEST_EQ( sv.rfind( "23", 3 ), 1 ); + BOOST_TEST_EQ( sv.rfind( "23", 2 ), 1 ); + BOOST_TEST_EQ( sv.rfind( "23", 1 ), 1 ); + BOOST_TEST_EQ( sv.rfind( "23", 0 ), npos ); + + BOOST_TEST_EQ( sv.rfind( "123", npos, 0 ), 6 ); + BOOST_TEST_EQ( sv.rfind( "123", 7, 0 ), 6 ); + BOOST_TEST_EQ( sv.rfind( "123", 6, 0 ), 6 ); + BOOST_TEST_EQ( sv.rfind( "123", 5, 0 ), 5 ); + BOOST_TEST_EQ( sv.rfind( "123", 1, 0 ), 1 ); + BOOST_TEST_EQ( sv.rfind( "123", 0, 0 ), 0 ); + + BOOST_TEST_EQ( sv.rfind( "123", npos, 1 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "123", 7, 1 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "123", 6, 1 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "123", 5, 1 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "123", 4, 1 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "123", 3, 1 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "123", 2, 1 ), 0 ); + BOOST_TEST_EQ( sv.rfind( "123", 1, 1 ), 0 ); + BOOST_TEST_EQ( sv.rfind( "123", 0, 1 ), 0 ); + + BOOST_TEST_EQ( sv.rfind( "123", npos, 3 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "123", 7, 3 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "123", 6, 3 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "123", 5, 3 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "123", 4, 3 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "123", 3, 3 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "123", 2, 3 ), 0 ); + BOOST_TEST_EQ( sv.rfind( "123", 1, 3 ), 0 ); + BOOST_TEST_EQ( sv.rfind( "123", 0, 3 ), 0 ); + + BOOST_TEST_EQ( sv.rfind( "123123" ), 0 ); + BOOST_TEST_EQ( sv.rfind( "1231231" ), npos ); + } + + return boost::report_errors(); +} From 95e64ef71ffe0c13ad301f631bd445faeb4cb8fc Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 6 Oct 2021 17:45:10 +0300 Subject: [PATCH 037/258] Fix msvc-14.0 failure --- include/boost/core/string_view.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index 743443f..096970e 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -573,12 +573,12 @@ public: // relational operators - BOOST_CONSTEXPR friend bool operator==( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + BOOST_CXX14_CONSTEXPR friend bool operator==( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT { return sv1.compare( sv2 ) == 0; } - BOOST_CONSTEXPR friend bool operator!=( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + BOOST_CXX14_CONSTEXPR friend bool operator!=( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT { return sv1.compare( sv2 ) != 0; } From 09870f0739d99dcf2a51f50e73a658d2c02c40d6 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 8 Oct 2021 05:39:24 +0300 Subject: [PATCH 038/258] Add sv_find_first_of_test --- include/boost/core/string_view.hpp | 2 +- test/Jamfile.v2 | 1 + test/sv_find_first_of_test.cpp | 161 +++++++++++++++++++++++++++++ 3 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 test/sv_find_first_of_test.cpp diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index 096970e..f564316 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -563,7 +563,7 @@ public: BOOST_CONSTEXPR bool contains( Ch c ) const BOOST_NOEXCEPT { - return traits_type::find( data(), size(), c ) == 0; + return traits_type::find( data(), size(), c ) != 0; } BOOST_CONSTEXPR bool contains( Ch const* s ) const BOOST_NOEXCEPT diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 11bbea6..fcd33ea 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -259,6 +259,7 @@ run sv_starts_with_test.cpp ; run sv_ends_with_test.cpp ; run sv_find_test.cpp ; run sv_rfind_test.cpp ; +run sv_find_first_of_test.cpp ; use-project /boost/core/swap : ./swap ; build-project ./swap ; diff --git a/test/sv_find_first_of_test.cpp b/test/sv_find_first_of_test.cpp new file mode 100644 index 0000000..c32c23e --- /dev/null +++ b/test/sv_find_first_of_test.cpp @@ -0,0 +1,161 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include + +int main() +{ + std::size_t const npos = boost::core::string_view::npos; + + { + boost::core::string_view sv( "" ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view() ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view(), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "" ) ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "1" ) ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "1" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( '1' ), npos ); + BOOST_TEST_EQ( sv.find_first_of( '1', 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( "" ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( "1" ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "1", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( "12", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "12", 1, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( "12", 0, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "12", 1, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( "12", 0, 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "12", 1, 2 ), npos ); + } + + { + boost::core::string_view sv( "123123" ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view() ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view(), 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view(), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view(), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "" ) ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "" ), 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "1" ) ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "1" ), 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "1" ), 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "1" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "1" ), 4 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "1" ), 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "1" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "1" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "4" ) ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "4" ), 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "4" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "4" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "23" ) ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "23" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "23" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "23" ), 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "23" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "23" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "23" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "23" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( '1' ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( '1', 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( '1', 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( '1', 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( '1', 4 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( '1', 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( '1', 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( '1', 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( '3' ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( '3', 1 ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( '3', 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( '3', 3 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( '3', 4 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( '3', 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( '3', 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( '3', 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( '9' ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( "" ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "", 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( "1" ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( "1", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "1", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "1", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "1", 4 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "1", 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "1", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "1", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( "23" ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( "23", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( "23", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( "23", 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( "23", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( "23", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( "23", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "23", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( "123", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "123", 1, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "123", 2, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "123", 3, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "123", 4, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "123", 5, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "123", 6, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "123", 7, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( "123", 0, 1 ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 1, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 2, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 3, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 4, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "123", 5, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "123", 6, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "123", 7, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( "123", 0, 2 ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 1, 2 ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 2, 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 3, 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 4, 2 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 5, 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "123", 6, 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "123", 7, 2 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( "123", 0, 3 ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 1, 3 ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 2, 3 ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 3, 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 4, 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 5, 3 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 6, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "123", 7, 3 ), npos ); + } + + return boost::report_errors(); +} From d1ad50cefb222eeb713f01f807c1ac99142fc47d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 8 Oct 2021 05:50:00 +0300 Subject: [PATCH 039/258] Add sv_contains_test --- test/Jamfile.v2 | 1 + test/sv_contains_test.cpp | 71 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 test/sv_contains_test.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index fcd33ea..feb2011 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -260,6 +260,7 @@ run sv_ends_with_test.cpp ; run sv_find_test.cpp ; run sv_rfind_test.cpp ; run sv_find_first_of_test.cpp ; +run sv_contains_test.cpp ; use-project /boost/core/swap : ./swap ; build-project ./swap ; diff --git a/test/sv_contains_test.cpp b/test/sv_contains_test.cpp new file mode 100644 index 0000000..bb63491 --- /dev/null +++ b/test/sv_contains_test.cpp @@ -0,0 +1,71 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include + +int main() +{ + { + boost::core::string_view sv( "" ); + + BOOST_TEST( sv.contains( boost::core::string_view() ) ); + + BOOST_TEST( sv.contains( boost::core::string_view( "" ) ) ); + BOOST_TEST( !sv.contains( boost::core::string_view( "1" ) ) ); + + BOOST_TEST( !sv.contains( '1' ) ); + + BOOST_TEST( sv.contains( "" ) ); + BOOST_TEST( !sv.contains( "1" ) ); + } + + { + boost::core::string_view sv( "123123" ); + + BOOST_TEST( sv.contains( boost::core::string_view() ) ); + BOOST_TEST( sv.contains( boost::core::string_view( "" ) ) ); + + BOOST_TEST( sv.contains( boost::core::string_view( "1" ) ) ); + BOOST_TEST( sv.contains( boost::core::string_view( "2" ) ) ); + BOOST_TEST( sv.contains( boost::core::string_view( "3" ) ) ); + BOOST_TEST( !sv.contains( boost::core::string_view( "4" ) ) ); + + BOOST_TEST( sv.contains( boost::core::string_view( "12" ) ) ); + BOOST_TEST( sv.contains( boost::core::string_view( "23" ) ) ); + BOOST_TEST( !sv.contains( boost::core::string_view( "34" ) ) ); + BOOST_TEST( !sv.contains( boost::core::string_view( "21" ) ) ); + + BOOST_TEST( sv.contains( '1' ) ); + BOOST_TEST( sv.contains( '2' ) ); + BOOST_TEST( sv.contains( '3' ) ); + BOOST_TEST( !sv.contains( '4' ) ); + + BOOST_TEST( sv.contains( "" ) ); + + BOOST_TEST( sv.contains( "1" ) ); + BOOST_TEST( sv.contains( "2" ) ); + BOOST_TEST( sv.contains( "3" ) ); + BOOST_TEST( !sv.contains( "4" ) ); + + BOOST_TEST( sv.contains( "12" ) ); + BOOST_TEST( sv.contains( "23" ) ); + BOOST_TEST( !sv.contains( "34" ) ); + BOOST_TEST( !sv.contains( "21" ) ); + + BOOST_TEST( sv.contains( "123" ) ); + BOOST_TEST( !sv.contains( "234" ) ); + BOOST_TEST( sv.contains( "231" ) ); + BOOST_TEST( !sv.contains( "321" ) ); + + BOOST_TEST( !sv.contains( "1234" ) ); + BOOST_TEST( sv.contains( "1231" ) ); + + BOOST_TEST( sv.contains( "123123" ) ); + BOOST_TEST( !sv.contains( "1231231" ) ); + } + + return boost::report_errors(); +} From df65ea66002ff2be6e320f09620dea0d4b10405d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 8 Oct 2021 06:21:52 +0300 Subject: [PATCH 040/258] Update sv_find_first_of_test --- test/sv_find_first_of_test.cpp | 223 +++++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) diff --git a/test/sv_find_first_of_test.cpp b/test/sv_find_first_of_test.cpp index c32c23e..e3f832a 100644 --- a/test/sv_find_first_of_test.cpp +++ b/test/sv_find_first_of_test.cpp @@ -41,6 +41,37 @@ int main() BOOST_TEST_EQ( sv.find_first_of( "12", 1, 2 ), npos ); } + { + boost::core::wstring_view sv( L"" ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view() ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view(), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"" ) ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"1" ) ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"1" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L'1' ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L'1', 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"" ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"1" ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"1", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"12", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"12", 1, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"12", 0, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"12", 1, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"12", 0, 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"12", 1, 2 ), npos ); + } + { boost::core::string_view sv( "123123" ); @@ -157,5 +188,197 @@ int main() BOOST_TEST_EQ( sv.find_first_of( "123", 7, 3 ), npos ); } + { + boost::core::wstring_view sv( L"123123" ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view() ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view(), 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view(), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view(), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"" ) ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"" ), 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"1" ) ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"1" ), 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"1" ), 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"1" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"1" ), 4 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"1" ), 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"1" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"1" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"4" ) ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"4" ), 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"4" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"4" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"23" ) ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"23" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"23" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"23" ), 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"23" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"23" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"23" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"23" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L'1' ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( L'1', 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L'1', 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L'1', 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L'1', 4 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L'1', 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L'1', 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L'1', 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L'3' ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( L'3', 1 ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( L'3', 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( L'3', 3 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( L'3', 4 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( L'3', 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( L'3', 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L'3', 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L'9' ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"" ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"", 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"1" ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( L"1", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"1", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"1", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"1", 4 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"1", 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"1", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"1", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"23" ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( L"23", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( L"23", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( L"23", 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( L"23", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( L"23", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( L"23", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"23", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"123", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 1, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 2, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 3, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 4, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 5, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 6, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 7, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"123", 0, 1 ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 1, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 2, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 3, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 4, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 5, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 6, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 7, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"123", 0, 2 ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 1, 2 ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 2, 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 3, 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 4, 2 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 5, 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 6, 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 7, 2 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"123", 0, 3 ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 1, 3 ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 2, 3 ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 3, 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 4, 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 5, 3 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 6, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 7, 3 ), npos ); + } + + { + boost::core::string_view sv( "abc1abc2abc3" ); + + BOOST_TEST_EQ( sv.find_first_of( "0123456789" ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "0123456789", 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "0123456789", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "0123456789", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "0123456789", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "0123456789", 4 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( "0123456789", 5 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( "0123456789", 6 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( "0123456789", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( "0123456789", 8 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( "0123456789", 9 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( "0123456789", 10 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( "0123456789", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( "0123456789", 12 ), npos ); + } + + { + boost::core::wstring_view sv( L"abc1abc2abc3" ); + + BOOST_TEST_EQ( sv.find_first_of( L"0123456789" ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"0123456789", 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"0123456789", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"0123456789", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"0123456789", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"0123456789", 4 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( L"0123456789", 5 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( L"0123456789", 6 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( L"0123456789", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( L"0123456789", 8 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( L"0123456789", 9 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( L"0123456789", 10 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( L"0123456789", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( L"0123456789", 12 ), npos ); + } + + { + boost::core::string_view sv( "123a123B123c" ); + + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 4 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 5 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 6 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 8 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 9 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 10 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 12 ), npos ); + } + + { + boost::core::wstring_view sv( L"123a123B123c" ); + + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 4 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 5 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 6 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 8 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 9 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 10 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 12 ), npos ); + } + return boost::report_errors(); } From 18334b1614cb9f3d469982d19a42eef958c69c33 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 8 Oct 2021 07:03:39 +0300 Subject: [PATCH 041/258] Add optimized implementation of find_first_of --- include/boost/core/string_view.hpp | 102 ++++++++++++++++++++++++++--- 1 file changed, 92 insertions(+), 10 deletions(-) diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index f564316..d57a5a3 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -25,6 +25,7 @@ #include #include #include +#include #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) # include #endif @@ -33,6 +34,89 @@ namespace boost { namespace core { +namespace detail +{ + +template BOOST_CXX14_CONSTEXPR std::size_t find_first_of( Ch const* p_, std::size_t n_, Ch const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT +{ + if( n >= 16 ) + { + for( std::size_t i = pos; i < n_; ++i ) + { + Ch ch = p_[ i ]; + if( std::char_traits::find( s, n, ch ) != 0 ) return i; + } + } + else + { + for( std::size_t i = pos; i < n_; ++i ) + { + Ch ch = p_[ i ]; + + for( std::size_t j = 0; j < n; ++j ) + { + if( s[ j ] == ch ) return i; + } + } + } + + return static_cast( -1 ); +} + +#if CHAR_BIT == 8 + +BOOST_CXX14_CONSTEXPR std::size_t find_first_of( char const* p_, std::size_t n_, char const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT +{ + unsigned char table[ 256 ] = {}; + + unsigned char r = 0; + boost::uint64_t mask = 0; + + for( std::size_t j = 0; j < n; ++j ) + { + unsigned char ch = s[ j ]; + + table[ ch ] = 1; + + r |= ch; + + mask |= boost::uint64_t( 1 ) << ( ch & 0x3F ); + } + + if( ( r & 0xC0 ) == 0 ) + { + for( std::size_t i = pos; i < n_; ++i ) + { + unsigned char ch = p_[ i ]; + if( mask & ( boost::uint64_t( 1 ) << ch ) ) return i; + } + + return static_cast( -1 ); + } + else + { + for( std::size_t i = pos; i < n_; ++i ) + { + unsigned char ch = p_[ i ]; + if( table[ ch ] ) return i; + } + + return static_cast( -1 ); + } +} + +#endif + +#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L + +std::size_t find_first_of( char8_t const* p_, std::size_t n_, char8_t const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT +{ + return detail::find_first_of( reinterpret_cast< char const* >( p_ ), n_, reinterpret_cast< char const* >( s ), pos, n ); +} + +#endif + +} // namespace detail template class basic_string_view { @@ -425,12 +509,7 @@ public: BOOST_CXX14_CONSTEXPR size_type find_first_of( basic_string_view str, size_type pos = 0 ) const BOOST_NOEXCEPT { - for( std::size_t i = pos; i < n_; ++i ) - { - if( str.contains( p_[ i ] ) ) return i; - } - - return npos; + return find_first_of( str.data(), pos, str.size() ); } BOOST_CONSTEXPR size_type find_first_of( Ch c, size_type pos = 0 ) const BOOST_NOEXCEPT @@ -438,14 +517,17 @@ public: return find( c, pos ); } - BOOST_CONSTEXPR size_type find_first_of( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT + BOOST_CXX14_CONSTEXPR size_type find_first_of( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT { - return find_first_of( basic_string_view( s, n ), pos ); + if( n == 0 || pos >= size() ) return npos; + if( n == 1 ) return find( s[0], pos ); + + return detail::find_first_of( data(), size(), s, pos, n ); } - BOOST_CONSTEXPR size_type find_first_of( Ch const* s, size_type pos = 0 ) const BOOST_NOEXCEPT + BOOST_CXX14_CONSTEXPR size_type find_first_of( Ch const* s, size_type pos = 0 ) const BOOST_NOEXCEPT { - return find_first_of( basic_string_view( s ), pos ); + return find_first_of( s, pos, traits_type::length( s ) ); } // find_last_of From 8223ff03e41524d1960fb675ef682e782ceb22e2 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 8 Oct 2021 07:14:54 +0300 Subject: [PATCH 042/258] Add char8_t tests to sv_find_first_of_test --- test/sv_find_first_of_test.cpp | 78 ++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/test/sv_find_first_of_test.cpp b/test/sv_find_first_of_test.cpp index e3f832a..445ee58 100644 --- a/test/sv_find_first_of_test.cpp +++ b/test/sv_find_first_of_test.cpp @@ -380,5 +380,83 @@ int main() BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 12 ), npos ); } +#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L + + { + boost::core::u8string_view sv( u8"123123" ); + + BOOST_TEST_EQ( sv.find_first_of( u8"" ), npos ); + BOOST_TEST_EQ( sv.find_first_of( u8"", 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( u8"", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( u8"", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( u8"1" ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( u8"1", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"1", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"1", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"1", 4 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( u8"1", 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( u8"1", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( u8"1", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( u8"23" ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( u8"23", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( u8"23", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( u8"23", 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( u8"23", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( u8"23", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( u8"23", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( u8"23", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( u8"123", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( u8"123", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( u8"123", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( u8"123", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"123", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( u8"123", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( u8"123", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( u8"123", 7 ), npos ); + } + + { + boost::core::u8string_view sv( u8"abc1abc2abc3" ); + + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789" ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789", 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789", 4 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789", 5 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789", 6 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789", 8 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789", 9 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789", 10 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789", 12 ), npos ); + } + + { + boost::core::u8string_view sv( u8"123a123B123c" ); + + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 4 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 5 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 6 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 8 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 9 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 10 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 12 ), npos ); + } + +#endif + return boost::report_errors(); } From 41c3b6a7ddce3f3610c83d9e8fd5f22cd5a388f3 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 8 Oct 2021 09:23:26 +0300 Subject: [PATCH 043/258] Reimplement type_name with class templates to avoid instantiating types such as pair and tuple --- include/boost/core/type_name.hpp | 857 +++++++++++++++++++------------ test/type_name_test.cpp | 26 + 2 files changed, 559 insertions(+), 324 deletions(-) diff --git a/include/boost/core/type_name.hpp b/include/boost/core/type_name.hpp index 5512c0c..bb20f99 100644 --- a/include/boost/core/type_name.hpp +++ b/include/boost/core/type_name.hpp @@ -160,28 +160,28 @@ template std::string typeid_name() template std::string class_template_name() { - std::string r = typeid_name(); + std::string r = typeid_name(); return r.substr( 0, r.find( '<' ) ); } template std::string sequence_template_name() { - return class_template_name(); + return detail::class_template_name(); } template std::string set_template_name() { - return class_template_name(); + return detail::class_template_name(); } template std::string map_template_name() { - return class_template_name(); + return detail::class_template_name(); } template std::string array_template_name() { - return class_template_name(); + return detail::class_template_name(); } #else // #if !defined(BOOST_NO_TYPEID) @@ -237,14 +237,156 @@ inline std::string tn_to_string( std::size_t n ) # pragma warning( pop ) #endif -// tn_add_each +// tn_holder + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return typeid_name() + suffix; + } +}; + +// integrals + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "unsigned" + suffix; + } +}; + +#if defined(_MSC_VER) + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "long long" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "unsigned long long" + suffix; + } +}; + +#endif + +#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "char8_t" + suffix; + } +}; + +#endif + +// cv + +#if 1 // !defined(BOOST_MSVC) || BOOST_MSVC >= 1900 + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return tn_holder::type_name( " const" + suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return tn_holder::type_name( " volatile" + suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return tn_holder::type_name( " const volatile" + suffix ); + } +}; + +#else + +template +typename tn_enable_if::value, std::string>::type +type_name( tn_identity, std::string const& suffix ) +{ + return detail::type_name( tn_identity(), " const" + suffix ); +} + +template +typename tn_enable_if::value, std::string>::type +type_name( tn_identity, std::string const& suffix ) +{ + return detail::type_name( tn_identity(), " volatile" + suffix ); +} + +template +typename tn_enable_if::value, std::string>::type +type_name( tn_identity, std::string const& suffix ) +{ + return detail::type_name( tn_identity(), " const volatile" + suffix ); +} + +#endif + +// refs + +#if 1 // !defined(BOOST_MSVC) || BOOST_MSVC >= 1900 + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return tn_holder::type_name( "&" + suffix ); + } +}; + +#else + +template +typename tn_enable_if::value, std::string>::type +type_name( tn_identity, std::string const& suffix ) +{ + return detail::type_name( tn_identity(), "&" + suffix ); +} + +#endif + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return tn_holder::type_name( "&&" + suffix ); + } +}; + +#endif + +// function types #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +// tn_add_each + template int tn_add_each_impl( std::string& st ) { if( !st.empty() ) st += ", "; - st += type_name( tn_identity(), "" ); + st += tn_holder::type_name( "" ); return 0; } @@ -258,125 +400,9 @@ template std::string tn_add_each() return st; } -#endif - -// primary - -template std::string type_name( tn_identity, std::string const& suffix ) -{ - return typeid_name() + suffix; -} - -// integrals - -inline std::string type_name( tn_identity, std::string const& suffix ) -{ - return "unsigned" + suffix; -} - -#if defined(_MSC_VER) - -inline std::string type_name( tn_identity, std::string const& suffix ) -{ - return "long long" + suffix; -} - -inline std::string type_name( tn_identity, std::string const& suffix ) -{ - return "unsigned long long" + suffix; -} - -#endif - -#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L - -inline std::string type_name( tn_identity, std::string const& suffix ) -{ - return "char8_t" + suffix; -} - -#endif - -// cv - -#if !defined(BOOST_MSVC) || BOOST_MSVC >= 1900 - -template std::string type_name( tn_identity, std::string const& suffix ) -{ - return type_name( tn_identity(), " const" + suffix ); -} - -template std::string type_name( tn_identity, std::string const& suffix ) -{ - return type_name( tn_identity(), " volatile" + suffix ); -} - -template std::string type_name( tn_identity, std::string const& suffix ) -{ - return type_name( tn_identity(), " const volatile" + suffix ); -} - -#else - -template -typename tn_enable_if::value, std::string>::type -type_name( tn_identity, std::string const& suffix ) -{ - return type_name( tn_identity(), " const" + suffix ); -} - -template -typename tn_enable_if::value, std::string>::type -type_name( tn_identity, std::string const& suffix ) -{ - return type_name( tn_identity(), " volatile" + suffix ); -} - -template -typename tn_enable_if::value, std::string>::type -type_name( tn_identity, std::string const& suffix ) -{ - return type_name( tn_identity(), " const volatile" + suffix ); -} - -#endif - -// refs - -#if !defined(BOOST_MSVC) || BOOST_MSVC >= 1900 - -template std::string type_name( tn_identity, std::string const& suffix ) -{ - return type_name( tn_identity(), "&" + suffix ); -} - -#else - -template -typename tn_enable_if::value, std::string>::type -type_name( tn_identity, std::string const& suffix ) -{ - return type_name( tn_identity(), "&" + suffix ); -} - -#endif - -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - -template std::string type_name( tn_identity, std::string const& suffix ) -{ - return type_name( tn_identity(), "&&" + suffix ); -} - -#endif - -// function types - -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - template std::string function_type_name( tn_identity, std::string const& trailer, std::string const& suffix ) { - std::string r = type_name( tn_identity(), "" ); + std::string r = tn_holder::type_name( "" ); if( !suffix.empty() ) { @@ -400,135 +426,207 @@ template std::string function_type_name( tn_identity std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), "", suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), "", suffix ); + } +}; #if !defined(BOOST_MSVC) || BOOST_MSVC >= 1900 -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), " const", suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const", suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), " volatile", suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " volatile", suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), " const volatile", suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const volatile", suffix ); + } +}; #endif #if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), " &", suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " &", suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), " const &", suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const &", suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), " volatile &", suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " volatile &", suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), " const volatile &", suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const volatile &", suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), " &&", suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " &&", suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), " const &&", suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const &&", suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), " volatile &&", suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " volatile &&", suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), " const volatile &&", suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const volatile &&", suffix ); + } +}; #endif #if defined( __cpp_noexcept_function_type ) || defined( _NOEXCEPT_TYPES_SUPPORTED ) -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), " noexcept", suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " noexcept", suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), " const noexcept", suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const noexcept", suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), " volatile noexcept", suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " volatile noexcept", suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), " const volatile noexcept", suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const volatile noexcept", suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), " & noexcept", suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " & noexcept", suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), " const & noexcept", suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const & noexcept", suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), " volatile & noexcept", suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " volatile & noexcept", suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), " const volatile & noexcept", suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const volatile & noexcept", suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), " && noexcept", suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " && noexcept", suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), " const && noexcept", suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const && noexcept", suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), " volatile && noexcept", suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " volatile && noexcept", suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), " const volatile && noexcept", suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const volatile && noexcept", suffix ); + } +}; #endif @@ -536,21 +634,24 @@ template std::string type_name( tn_identity std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return type_name( tn_identity(), "*" + suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return tn_holder::type_name( "*" + suffix ); + } +}; // arrays template std::pair array_prefix_suffix( tn_identity ) { - return std::pair( type_name( tn_identity(), "" ), "" ); + return std::pair( tn_holder::type_name( "" ), "" ); } template std::pair array_prefix_suffix( tn_identity ) { - std::pair r = array_prefix_suffix( tn_identity() ); + std::pair r = detail::array_prefix_suffix( tn_identity() ); r.second = '[' + tn_to_string( N ) + ']' + r.second; @@ -559,7 +660,7 @@ template std::pair array_prefi template std::string array_type_name( tn_identity, std::string const& suffix ) { - std::pair r = array_prefix_suffix( tn_identity() ); + std::pair r = detail::array_prefix_suffix( tn_identity() ); if( suffix.empty() ) { @@ -571,29 +672,41 @@ template std::string array_type_name( tn_identity, std::string con } } -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return array_type_name( tn_identity(), suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::array_type_name( tn_identity(), suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return array_type_name( tn_identity(), suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::array_type_name( tn_identity(), suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return array_type_name( tn_identity(), suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::array_type_name( tn_identity(), suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return array_type_name( tn_identity(), suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::array_type_name( tn_identity(), suffix ); + } +}; template std::string array_type_name( tn_identity, std::string const& suffix ) { - std::pair r = array_prefix_suffix( tn_identity() ); + std::pair r = detail::array_prefix_suffix( tn_identity() ); if( suffix.empty() ) { @@ -605,54 +718,81 @@ template std::string array_type_name( tn_identity, } } -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return array_type_name( tn_identity(), suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::array_type_name( tn_identity(), suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return array_type_name( tn_identity(), suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::array_type_name( tn_identity(), suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return array_type_name( tn_identity(), suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::array_type_name( tn_identity(), suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return array_type_name( tn_identity(), suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::array_type_name( tn_identity(), suffix ); + } +}; // pointers to members -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return type_name( tn_identity(), ' ' + type_name( tn_identity(), "" ) + "::*" + suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return tn_holder::type_name( ' ' + tn_holder::type_name( "" ) + "::*" + suffix ); + } +}; #if defined(BOOST_MSVC) && BOOST_MSVC < 1900 && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), "", ' ' + type_name( tn_identity(), "" ) + "::*" + suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), "", ' ' + tn_holder::type_name( "" ) + "::*" + suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), " const", ' ' + type_name( tn_identity(), "" ) + "::*" + suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const", ' ' + tn_holder::type_name( "" ) + "::*" + suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), " volatile", ' ' + type_name( tn_identity(), "" ) + "::*" + suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " volatile", ' ' + tn_holder::type_name( "" ) + "::*" + suffix ); + } +}; -template std::string type_name( tn_identity, std::string const& suffix ) +template struct tn_holder { - return function_type_name( tn_identity(), " const volatile", ' ' + type_name( tn_identity(), "" ) + "::*" + suffix ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const volatile", ' ' + tn_holder::type_name( "" ) + "::*" + suffix ); + } +}; #endif @@ -660,108 +800,150 @@ template std::string type_name( tn_identity, std::string const& suffix ) +template<> struct tn_holder { - return "std::nullptr_t" + suffix; -} + static std::string type_name( std::string const& suffix ) + { + return "std::nullptr_t" + suffix; + } +}; #endif // strings -template class L, class Ch> std::string type_name( tn_identity< L, std::allocator > >, std::string const& suffix ) +template class L, class Ch> struct tn_holder< L, std::allocator > > { - std::string tn = sequence_template_name< L, std::allocator > >(); - return tn + '<' + type_name( tn_identity(), "" ) + '>' + suffix; -} + static std::string type_name( std::string const& suffix ) + { + std::string tn = sequence_template_name< L, std::allocator > >(); + return tn + '<' + tn_holder::type_name( "" ) + '>' + suffix; + } +}; -inline std::string type_name( tn_identity, std::string const& suffix ) +template<> struct tn_holder { - return "std::string" + suffix; -} + static std::string type_name( std::string const& suffix ) + { + return "std::string" + suffix; + } +}; -inline std::string type_name( tn_identity, std::string const& suffix ) +template<> struct tn_holder { - return "std::wstring" + suffix; -} + static std::string type_name( std::string const& suffix ) + { + return "std::wstring" + suffix; + } +}; #if !defined(BOOST_NO_CXX11_CHAR16_T) -inline std::string type_name( tn_identity, std::string const& suffix ) +template<> struct tn_holder { - return "std::u16string" + suffix; -} + static std::string type_name( std::string const& suffix ) + { + return "std::u16string" + suffix; + } +}; #endif #if !defined(BOOST_NO_CXX11_CHAR32_T) -inline std::string type_name( tn_identity, std::string const& suffix ) +template<> struct tn_holder { - return "std::u32string" + suffix; -} + static std::string type_name( std::string const& suffix ) + { + return "std::u32string" + suffix; + } +}; #endif #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L -inline std::string type_name( tn_identity>, std::string const& suffix ) +template<> struct tn_holder< std::basic_string > { - return "std::u8string" + suffix; -} + static std::string type_name( std::string const& suffix ) + { + return "std::u8string" + suffix; + } +}; #endif // string views (et al) -template class L, class Ch> std::string type_name( tn_identity< L > >, std::string const& suffix ) +template class L, class Ch> struct tn_holder< L > > { - std::string tn = sequence_template_name< L > >(); - return tn + '<' + type_name( tn_identity(), "" ) + '>' + suffix; -} + static std::string type_name( std::string const& suffix ) + { + std::string tn = sequence_template_name< L > >(); + return tn + '<' + tn_holder::type_name( "" ) + '>' + suffix; + } +}; // needed for libstdc++ -inline std::string type_name( tn_identity, std::string const& suffix ) +template<> struct tn_holder { - return "std::ostream" + suffix; -} + static std::string type_name( std::string const& suffix ) + { + return "std::ostream" + suffix; + } +}; #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) -inline std::string type_name( tn_identity, std::string const& suffix ) +template<> struct tn_holder { - return "std::string_view" + suffix; -} + static std::string type_name( std::string const& suffix ) + { + return "std::string_view" + suffix; + } +}; -inline std::string type_name( tn_identity, std::string const& suffix ) +template<> struct tn_holder { - return "std::wstring_view" + suffix; -} + static std::string type_name( std::string const& suffix ) + { + return "std::wstring_view" + suffix; + } +}; #if !defined(BOOST_NO_CXX11_CHAR16_T) -inline std::string type_name( tn_identity, std::string const& suffix ) +template<> struct tn_holder { - return "std::u16string_view" + suffix; -} + static std::string type_name( std::string const& suffix ) + { + return "std::u16string_view" + suffix; + } +}; #endif #if !defined(BOOST_NO_CXX11_CHAR32_T) -inline std::string type_name( tn_identity, std::string const& suffix ) +template<> struct tn_holder { - return "std::u32string_view" + suffix; -} + static std::string type_name( std::string const& suffix ) + { + return "std::u32string_view" + suffix; + } +}; #endif #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L -inline std::string type_name( tn_identity>, std::string const& suffix ) +template<> struct tn_holder< std::basic_string_view > { - return "std::u8string_view" + suffix; -} + static std::string type_name( std::string const& suffix ) + { + return "std::u8string_view" + suffix; + } +}; #endif @@ -771,87 +953,114 @@ inline std::string type_name( tn_identity>, std: #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) -template class L, class... T> std::string type_name( tn_identity< L >, std::string const& suffix ) +template class L, class... T> struct tn_holder< L > { - std::string tn = class_template_name< L >(); - std::string st = tn_add_each(); + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::class_template_name< L >(); + std::string st = tn_add_each(); - return tn + '<' + st + '>' + suffix; -} + return tn + '<' + st + '>' + suffix; + } +}; #else -template class L, class T1> std::string type_name( tn_identity< L >, std::string const& suffix ) +template class L, class T1> struct tn_holder< L > { - std::string tn = class_template_name< L >(); - return tn + '<' + type_name( tn_identity(), "" ) + '>' + suffix; -} + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::class_template_name< L >(); + return tn + '<' + tn_holder::type_name( "" ) + '>' + suffix; + } +}; -template class L, class T1, class T2> std::string type_name( tn_identity< L >, std::string const& suffix ) +template class L, class T1, class T2> struct tn_holder< L > { - std::string tn = class_template_name< L >(); - return tn + '<' + type_name( tn_identity(), "" ) + ", " + type_name( tn_identity(), "" ) + '>' + suffix; -} + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::class_template_name< L >(); + return tn + '<' + tn_holder::type_name( "" ) + ", " + tn_holder::type_name( "" ) + '>' + suffix; + } +}; #endif // sequence containers -template class L, class T> std::string type_name( tn_identity< L > >, std::string const& suffix ) +template class L, class T> struct tn_holder< L > > { - std::string tn = sequence_template_name< L > >(); - return tn + '<' + type_name( tn_identity(), "" ) + '>' + suffix; -} + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::sequence_template_name< L > >(); + return tn + '<' + tn_holder::type_name( "" ) + '>' + suffix; + } +}; // set -template class L, class T> std::string type_name( tn_identity< L, std::allocator > >, std::string const& suffix ) +template class L, class T> struct tn_holder< L, std::allocator > > { - std::string tn = set_template_name< L, std::allocator > >(); - return tn + '<' + type_name( tn_identity(), "" ) + '>' + suffix; -} + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::set_template_name< L, std::allocator > >(); + return tn + '<' + tn_holder::type_name( "" ) + '>' + suffix; + } +}; // map -template class L, class T, class U> std::string type_name( tn_identity< L, std::allocator > > >, std::string const& suffix ) +template class L, class T, class U> struct tn_holder< L, std::allocator > > > { - std::string tn = map_template_name< L, std::allocator > > >(); - return tn + '<' + type_name( tn_identity(), "" ) + ", " + type_name( tn_identity(), "" ) + '>' + suffix; -} + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::map_template_name< L, std::allocator > > >(); + return tn + '<' + tn_holder::type_name( "" ) + ", " + tn_holder::type_name( "" ) + '>' + suffix; + } +}; #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) // unordered_set -template class L, class T> std::string type_name( tn_identity< L, std::equal_to, std::allocator > >, std::string const& suffix ) +template class L, class T> struct tn_holder< L, std::equal_to, std::allocator > > { - std::string tn = set_template_name< L, std::equal_to, std::allocator > >(); - return tn + '<' + type_name( tn_identity(), "" ) + '>' + suffix; -} + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::set_template_name< L, std::equal_to, std::allocator > >(); + return tn + '<' + tn_holder::type_name( "" ) + '>' + suffix; + } +}; // unordered_map -template class L, class T, class U> std::string type_name( tn_identity< L, std::equal_to, std::allocator > > >, std::string const& suffix ) +template class L, class T, class U> struct tn_holder< L, std::equal_to, std::allocator > > > { - std::string tn = map_template_name< L, std::equal_to, std::allocator > > >(); - return tn + '<' + type_name( tn_identity(), "" ) + ", " + type_name( tn_identity(), "" ) + '>' + suffix; -} + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::map_template_name< L, std::equal_to, std::allocator > > >(); + return tn + '<' + tn_holder::type_name( "" ) + ", " + tn_holder::type_name( "" ) + '>' + suffix; + } +}; #endif // array -template class L, class T, std::size_t N> std::string type_name( tn_identity< L >, std::string const& suffix ) +template class L, class T, std::size_t N> struct tn_holder< L > { - std::string tn = array_template_name< L >(); - return tn + '<' + type_name( tn_identity(), "" ) + ", " + tn_to_string( N ) + '>' + suffix; -} + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::array_template_name< L >(); + return tn + '<' + tn_holder::type_name( "" ) + ", " + tn_to_string( N ) + '>' + suffix; + } +}; } // namespace detail template std::string type_name() { - return core::detail::type_name( core::detail::tn_identity(), "" ); + return core::detail::tn_holder::type_name( "" ); } } // namespace core diff --git a/test/type_name_test.cpp b/test/type_name_test.cpp index 6b61def..03c2fcd 100644 --- a/test/type_name_test.cpp +++ b/test/type_name_test.cpp @@ -27,6 +27,10 @@ # include #endif +#if !defined(BOOST_NO_CXX11_HDR_TUPLE) +# include +#endif + #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) # include #endif @@ -265,6 +269,9 @@ int main() TEST(std::pair); TEST(std::pair volatile&); + TEST(std::pair); + TEST(std::pair, void>); + TEST(std::basic_string); TEST(std::string); @@ -286,6 +293,8 @@ int main() TEST(X); TEST(X volatile&); + TEST(X, void>); + TEST(std::vector); TEST(std::vector); TEST(std::vector); @@ -326,6 +335,23 @@ int main() TEST(std::array); TEST(std::array const&); +#endif + +#if !defined(BOOST_NO_CXX11_HDR_TUPLE) + + TEST(std::tuple<>); + TEST(std::tuple); + TEST(std::tuple); + TEST(std::tuple); + + TEST(std::tuple); + TEST(std::tuple); + TEST(std::tuple); + + TEST(std::tuple, void>); + + TEST(X, void>); + #endif TEST(std::ostream); From 706747ab085684e8cb6c6a9c59fec39375b4b2fa Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 8 Oct 2021 09:44:23 +0300 Subject: [PATCH 044/258] Work around g++'s instantiating X on typeid(X*) --- include/boost/core/type_name.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/boost/core/type_name.hpp b/include/boost/core/type_name.hpp index bb20f99..e6cdc49 100644 --- a/include/boost/core/type_name.hpp +++ b/include/boost/core/type_name.hpp @@ -160,7 +160,15 @@ template std::string typeid_name() template std::string class_template_name() { +#if defined(BOOST_GCC) + + std::string r = typeid_name(); + +#else + std::string r = typeid_name(); + +#endif return r.substr( 0, r.find( '<' ) ); } From d87766a7686d68af6270ebfa2a9e43f5789083d6 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 8 Oct 2021 10:14:21 +0300 Subject: [PATCH 045/258] Remove no longer necessary workarounds --- include/boost/core/type_name.hpp | 100 ------------------------------- 1 file changed, 100 deletions(-) diff --git a/include/boost/core/type_name.hpp b/include/boost/core/type_name.hpp index e6cdc49..8a118ad 100644 --- a/include/boost/core/type_name.hpp +++ b/include/boost/core/type_name.hpp @@ -31,7 +31,6 @@ namespace boost { namespace core { - namespace detail { @@ -42,65 +41,6 @@ template struct tn_identity typedef T type; }; -// tn_enable_if - -template struct tn_enable_if -{ -}; - -template struct tn_enable_if -{ - typedef T type; -}; - -// tn_is_reference - -template struct tn_is_reference -{ - static const bool value = false; -}; - -template struct tn_is_reference -{ - static const bool value = true; -}; - -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - -template struct tn_is_reference -{ - static const bool value = true; -}; - -#endif - -// tn_remove_const - -template struct tn_remove_const -{ - typedef T type; -}; - -template struct tn_remove_const -{ - typedef T type; -}; - -// tn_is_function (also catches references but that's OK) - -#if defined(BOOST_MSVC) -# pragma warning(push) -# pragma warning(disable: 4180 4181) -#endif - -template::type> struct tn_is_function: core::is_same -{ -}; - -#if defined(BOOST_MSVC) -# pragma warning(pop) -#endif - #if !defined(BOOST_NO_TYPEID) // typeid_name @@ -299,8 +239,6 @@ template<> struct tn_holder // cv -#if 1 // !defined(BOOST_MSVC) || BOOST_MSVC >= 1900 - template struct tn_holder { static std::string type_name( std::string const& suffix ) @@ -325,35 +263,8 @@ template struct tn_holder } }; -#else - -template -typename tn_enable_if::value, std::string>::type -type_name( tn_identity, std::string const& suffix ) -{ - return detail::type_name( tn_identity(), " const" + suffix ); -} - -template -typename tn_enable_if::value, std::string>::type -type_name( tn_identity, std::string const& suffix ) -{ - return detail::type_name( tn_identity(), " volatile" + suffix ); -} - -template -typename tn_enable_if::value, std::string>::type -type_name( tn_identity, std::string const& suffix ) -{ - return detail::type_name( tn_identity(), " const volatile" + suffix ); -} - -#endif - // refs -#if 1 // !defined(BOOST_MSVC) || BOOST_MSVC >= 1900 - template struct tn_holder { static std::string type_name( std::string const& suffix ) @@ -362,17 +273,6 @@ template struct tn_holder } }; -#else - -template -typename tn_enable_if::value, std::string>::type -type_name( tn_identity, std::string const& suffix ) -{ - return detail::type_name( tn_identity(), "&" + suffix ); -} - -#endif - #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) template struct tn_holder From af3e6a667bdb6497780214b203a89ba007ea977a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 8 Oct 2021 10:21:07 +0300 Subject: [PATCH 046/258] Update sv_find_first_of_test --- test/sv_find_first_of_test.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/sv_find_first_of_test.cpp b/test/sv_find_first_of_test.cpp index 445ee58..92e4188 100644 --- a/test/sv_find_first_of_test.cpp +++ b/test/sv_find_first_of_test.cpp @@ -4,6 +4,7 @@ #include #include +#include #include int main() @@ -380,6 +381,31 @@ int main() BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 12 ), npos ); } + { + char str[ 256 ]; + + for( int i = 0; i < 256; ++i ) + { + str[ i ] = static_cast< unsigned char >( i ); + } + + boost::core::string_view sv( str, 256 ); + + for( int i = 0; i < 256; ++i ) + { + std::string needle( 12, static_cast< unsigned char >( i ) ); + BOOST_TEST_EQ( sv.find_first_of( needle ), i ); + } + + std::reverse( str, str + 256 ); + + for( int i = 0; i < 256; ++i ) + { + std::string needle( 12, static_cast< unsigned char >( i ) ); + BOOST_TEST_EQ( sv.find_first_of( needle ), 255 - i ); + } + } + #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L { From be820fea2edc66e64a761a8c0248e6e43d3f712f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 8 Oct 2021 10:28:06 +0300 Subject: [PATCH 047/258] Remove uint64_t mask path from find_first_of; no longer a win after fix --- include/boost/core/string_view.hpp | 29 ++++------------------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index d57a5a3..cd71018 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -69,40 +69,19 @@ BOOST_CXX14_CONSTEXPR std::size_t find_first_of( char const* p_, std::size_t n_, { unsigned char table[ 256 ] = {}; - unsigned char r = 0; - boost::uint64_t mask = 0; - for( std::size_t j = 0; j < n; ++j ) { unsigned char ch = s[ j ]; - table[ ch ] = 1; - - r |= ch; - - mask |= boost::uint64_t( 1 ) << ( ch & 0x3F ); } - if( ( r & 0xC0 ) == 0 ) + for( std::size_t i = pos; i < n_; ++i ) { - for( std::size_t i = pos; i < n_; ++i ) - { - unsigned char ch = p_[ i ]; - if( mask & ( boost::uint64_t( 1 ) << ch ) ) return i; - } - - return static_cast( -1 ); + unsigned char ch = p_[ i ]; + if( table[ ch ] ) return i; } - else - { - for( std::size_t i = pos; i < n_; ++i ) - { - unsigned char ch = p_[ i ]; - if( table[ ch ] ) return i; - } - return static_cast( -1 ); - } + return static_cast( -1 ); } #endif From 85e24f0483aa1c78a78be0a37a8b5a33d4586e13 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 8 Oct 2021 18:21:04 +0300 Subject: [PATCH 048/258] Disable std::tuple tests on msvc-10.0 --- test/type_name_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/type_name_test.cpp b/test/type_name_test.cpp index 03c2fcd..3ed453b 100644 --- a/test/type_name_test.cpp +++ b/test/type_name_test.cpp @@ -337,7 +337,7 @@ int main() #endif -#if !defined(BOOST_NO_CXX11_HDR_TUPLE) +#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && ( !defined(BOOST_MSVC) || BOOST_MSVC >= 1700 ) TEST(std::tuple<>); TEST(std::tuple); From fe9c0164c0513cbf19b031815d7ba740e5d86d97 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 02:32:00 +0300 Subject: [PATCH 049/258] Add sv_find_last_of_test --- include/boost/core/string_view.hpp | 15 +- test/Jamfile.v2 | 1 + test/sv_find_last_of_test.cpp | 510 +++++++++++++++++++++++++++++ 3 files changed, 522 insertions(+), 4 deletions(-) create mode 100644 test/sv_find_last_of_test.cpp diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index cd71018..1e5b879 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -513,16 +513,23 @@ public: BOOST_CXX14_CONSTEXPR size_type find_last_of( basic_string_view str, size_type pos = npos ) const BOOST_NOEXCEPT { - if( pos > size() ) + if( size() == 0 ) { - pos = size(); + return npos; } - for( std::size_t i = pos; i > 0; --i ) + if( pos > size() - 1 ) { - if( str.contains( p_[ i - 1 ] ) ) return i - 1; + pos = size() - 1; } + do + { + if( str.contains( p_[ pos ] ) ) return pos; + --pos; + } + while( pos != npos ); + return npos; } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index feb2011..e481466 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -260,6 +260,7 @@ run sv_ends_with_test.cpp ; run sv_find_test.cpp ; run sv_rfind_test.cpp ; run sv_find_first_of_test.cpp ; +run sv_find_last_of_test.cpp ; run sv_contains_test.cpp ; use-project /boost/core/swap : ./swap ; diff --git a/test/sv_find_last_of_test.cpp b/test/sv_find_last_of_test.cpp new file mode 100644 index 0000000..2e85476 --- /dev/null +++ b/test/sv_find_last_of_test.cpp @@ -0,0 +1,510 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +int main() +{ + std::size_t const npos = boost::core::string_view::npos; + + { + boost::core::string_view sv( "" ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view() ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view(), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "" ) ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "1" ) ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "1" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( '1' ), npos ); + BOOST_TEST_EQ( sv.find_last_of( '1', 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( "" ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( "1" ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "1", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( "12", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "12", 1, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( "12", 0, 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "12", 1, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( "12", 0, 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "12", 1, 2 ), npos ); + } + + { + boost::core::wstring_view sv( L"" ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view() ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view(), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"" ) ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"1" ) ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"1" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( L'1' ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L'1', 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( L"" ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( L"1" ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"1", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( L"12", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"12", 1, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( L"12", 0, 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"12", 1, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( L"12", 0, 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"12", 1, 2 ), npos ); + } + + { + boost::core::string_view sv( "123123" ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view(), 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view(), 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view(), 6 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view(), 7 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view() ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "" ) ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "" ), 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "1" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "1" ), 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "1" ), 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "1" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "1" ), 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "1" ), 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "1" ), 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "1" ), 7 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "1" ) ), 3 ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "4" ), 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "4" ), 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "4" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "4" ), 7 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "4" ) ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "23" ), 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "23" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "23" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "23" ), 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "23" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "23" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "23" ), 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "23" ), 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "23" ) ), 5 ); + + BOOST_TEST_EQ( sv.find_last_of( '1', 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( '1', 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( '1', 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( '1', 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( '1', 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( '1', 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( '1', 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( '1', 7 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( '1' ), 3 ); + + BOOST_TEST_EQ( sv.find_last_of( '3', 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( '3', 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( '3', 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( '3', 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( '3', 4 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( '3', 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( '3', 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( '3', 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( '3' ), 5 ); + + BOOST_TEST_EQ( sv.find_last_of( '9' ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( "", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "", 6 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "", 7 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "" ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( "1", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( "1", 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( "1", 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( "1", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "1", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "1", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "1", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "1", 7 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "1" ), 3 ); + + BOOST_TEST_EQ( sv.find_last_of( "23", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "23", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( "23", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( "23", 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( "23", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( "23", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( "23", 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( "23", 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( "23" ), 5 ); + + BOOST_TEST_EQ( sv.find_last_of( "123", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "123", 1, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "123", 2, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "123", 3, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "123", 4, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "123", 5, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "123", 6, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "123", 7, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( "123", 0, 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 1, 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 2, 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 3, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 4, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 5, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 6, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 7, 1 ), 3 ); + + BOOST_TEST_EQ( sv.find_last_of( "123", 0, 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 1, 2 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 2, 2 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 3, 2 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 4, 2 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 5, 2 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 6, 2 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 7, 2 ), 4 ); + + BOOST_TEST_EQ( sv.find_last_of( "123", 0, 3 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 1, 3 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 2, 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 3, 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 4, 3 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 5, 3 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 6, 3 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 7, 3 ), 5 ); + } + + { + boost::core::wstring_view sv( L"123123" ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view(), 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view(), 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view(), 6 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view(), 7 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view() ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"" ) ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"" ), 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"1" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"1" ), 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"1" ), 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"1" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"1" ), 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"1" ), 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"1" ), 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"1" ), 7 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"1" ) ), 3 ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"4" ), 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"4" ), 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"4" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"4" ), 7 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"4" ) ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"23" ), 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"23" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"23" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"23" ), 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"23" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"23" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"23" ), 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"23" ), 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"23" ) ), 5 ); + + BOOST_TEST_EQ( sv.find_last_of( L'1', 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L'1', 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L'1', 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L'1', 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L'1', 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L'1', 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L'1', 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L'1', 7 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L'1' ), 3 ); + + BOOST_TEST_EQ( sv.find_last_of( L'3', 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L'3', 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L'3', 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( L'3', 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( L'3', 4 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( L'3', 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( L'3', 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( L'3', 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( L'3' ), 5 ); + + BOOST_TEST_EQ( sv.find_last_of( L'9' ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( L"", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"", 6 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"", 7 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"" ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( L"1", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L"1", 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L"1", 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L"1", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"1", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"1", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"1", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"1", 7 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"1" ), 3 ); + + BOOST_TEST_EQ( sv.find_last_of( L"23", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"23", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( L"23", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( L"23", 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( L"23", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( L"23", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( L"23", 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( L"23", 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( L"23" ), 5 ); + + BOOST_TEST_EQ( sv.find_last_of( L"123", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 1, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 2, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 3, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 4, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 5, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 6, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 7, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( L"123", 0, 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 1, 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 2, 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 3, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 4, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 5, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 6, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 7, 1 ), 3 ); + + BOOST_TEST_EQ( sv.find_last_of( L"123", 0, 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 1, 2 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 2, 2 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 3, 2 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 4, 2 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 5, 2 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 6, 2 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 7, 2 ), 4 ); + + BOOST_TEST_EQ( sv.find_last_of( L"123", 0, 3 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 1, 3 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 2, 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 3, 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 4, 3 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 5, 3 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 6, 3 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 7, 3 ), 5 ); + } + + { + boost::core::string_view sv( "abc1abc2abc3" ); + + BOOST_TEST_EQ( sv.find_last_of( "0123456789", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "0123456789", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "0123456789", 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "0123456789", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "0123456789", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "0123456789", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "0123456789", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "0123456789", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( "0123456789", 8 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( "0123456789", 9 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( "0123456789", 10 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( "0123456789", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_last_of( "0123456789", 12 ), 11 ); + BOOST_TEST_EQ( sv.find_last_of( "0123456789" ), 11 ); + } + + { + boost::core::wstring_view sv( L"abc1abc2abc3" ); + + BOOST_TEST_EQ( sv.find_last_of( L"0123456789", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"0123456789", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"0123456789", 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"0123456789", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"0123456789", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"0123456789", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"0123456789", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"0123456789", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( L"0123456789", 8 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( L"0123456789", 9 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( L"0123456789", 10 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( L"0123456789", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_last_of( L"0123456789", 12 ), 11 ); + BOOST_TEST_EQ( sv.find_last_of( L"0123456789" ), 11 ); + } + + { + boost::core::string_view sv( "123a123B123c" ); + + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 8 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 9 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 10 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 12 ), 11 ); + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ), 11 ); + } + + { + boost::core::wstring_view sv( L"123a123B123c" ); + + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 8 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 9 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 10 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 12 ), 11 ); + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ), 11 ); + } + + { + char str[ 256 ]; + + for( int i = 0; i < 256; ++i ) + { + str[ i ] = static_cast< unsigned char >( i ); + } + + boost::core::string_view sv( str, 256 ); + + for( int i = 0; i < 256; ++i ) + { + std::string needle( 12, static_cast< unsigned char >( i ) ); + BOOST_TEST_EQ( sv.find_last_of( needle ), i ); + } + + std::reverse( str, str + 256 ); + + for( int i = 0; i < 256; ++i ) + { + std::string needle( 12, static_cast< unsigned char >( i ) ); + BOOST_TEST_EQ( sv.find_last_of( needle ), 255 - i ); + } + } + +#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L + + { + boost::core::u8string_view sv( u8"123123" ); + + BOOST_TEST_EQ( sv.find_last_of( u8"", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( u8"", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( u8"", 6 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( u8"", 7 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( u8"" ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( u8"1", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( u8"1", 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( u8"1", 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( u8"1", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"1", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"1", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"1", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"1", 7 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"1" ), 3 ); + + BOOST_TEST_EQ( sv.find_last_of( u8"23", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( u8"23", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( u8"23", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( u8"23", 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( u8"23", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( u8"23", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( u8"23", 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( u8"23", 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( u8"23" ), 5 ); + + BOOST_TEST_EQ( sv.find_last_of( u8"123", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( u8"123", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( u8"123", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( u8"123", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"123", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( u8"123", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( u8"123", 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( u8"123", 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( u8"123" ), 5 ); + } + + { + boost::core::u8string_view sv( u8"abc1abc2abc3" ); + + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789", 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789", 8 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789", 9 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789", 10 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789", 12 ), 11 ); + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789" ), 11 ); + } + + { + boost::core::u8string_view sv( u8"123a123B123c" ); + + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 8 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 9 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 10 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 12 ), 11 ); + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ), 11 ); + } + +#endif + + return boost::report_errors(); +} From ab3950fdfb70885ace53a59d999e5d9f621f3291 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 03:09:32 +0300 Subject: [PATCH 050/258] Add sv_find_first_not_of_test --- test/Jamfile.v2 | 1 + test/sv_find_first_not_of_test.cpp | 573 +++++++++++++++++++++++++++++ 2 files changed, 574 insertions(+) create mode 100644 test/sv_find_first_not_of_test.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index e481466..400f0d8 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -261,6 +261,7 @@ run sv_find_test.cpp ; run sv_rfind_test.cpp ; run sv_find_first_of_test.cpp ; run sv_find_last_of_test.cpp ; +run sv_find_first_not_of_test.cpp ; run sv_contains_test.cpp ; use-project /boost/core/swap : ./swap ; diff --git a/test/sv_find_first_not_of_test.cpp b/test/sv_find_first_not_of_test.cpp new file mode 100644 index 0000000..e0258b5 --- /dev/null +++ b/test/sv_find_first_not_of_test.cpp @@ -0,0 +1,573 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +int main() +{ + std::size_t const npos = boost::core::string_view::npos; + + { + boost::core::string_view sv( "" ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view() ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view(), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "" ) ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "1" ) ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "1" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( '1' ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( '1', 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( "" ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( "1" ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "1", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( "12", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "12", 1, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( "12", 0, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "12", 1, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( "12", 0, 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "12", 1, 2 ), npos ); + } + + { + boost::core::wstring_view sv( L"" ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view() ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view(), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"" ) ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"1" ) ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"1" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L'1' ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L'1', 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"" ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"1" ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"1", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"12", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"12", 1, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"12", 0, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"12", 1, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"12", 0, 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"12", 1, 2 ), npos ); + } + + { + boost::core::string_view sv( "123123" ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view() ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view(), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view(), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view(), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view(), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view(), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view(), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view(), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view(), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "" ) ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "1" ) ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "1" ), 0 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "1" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "1" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "1" ), 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "1" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "1" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "1" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "1" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "4" ) ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "4" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "4" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "4" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "4" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "4" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "4" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "4" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "4" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "23" ) ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "23" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "23" ), 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "23" ), 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "23" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "23" ), 4 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "23" ), 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "23" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "23" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( '1' ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( '1', 0 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( '1', 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( '1', 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( '1', 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( '1', 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( '1', 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( '1', 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( '1', 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( '3' ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( '3', 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( '3', 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( '3', 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( '3', 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( '3', 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( '3', 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( '3', 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( '3', 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( '9' ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( '9', 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( '9', 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( '9', 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( '9', 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( '9', 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( '9', 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( '9', 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( '9', 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( "" ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( "", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( "", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( "", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( "", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( "", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( "", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( "1" ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( "1", 0 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( "1", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( "1", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( "1", 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( "1", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( "1", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( "1", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "1", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( "23" ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( "23", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( "23", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "23", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "23", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "23", 4 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "23", 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "23", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "23", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( "123", 0, 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 1, 0 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 2, 0 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 3, 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 4, 0 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 5, 0 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 6, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 7, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( "123", 0, 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 1, 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 2, 1 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 3, 1 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 4, 1 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 5, 1 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 6, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 7, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( "123", 0, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 1, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 2, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 3, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 4, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 5, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 6, 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 7, 2 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( "123", 0, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 1, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 2, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 3, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 4, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 5, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 6, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 7, 3 ), npos ); + } + + { + boost::core::wstring_view sv( L"123123" ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view() ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view(), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view(), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view(), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view(), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view(), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view(), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view(), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view(), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"" ) ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"1" ) ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"1" ), 0 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"1" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"1" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"1" ), 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"1" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"1" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"1" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"1" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"4" ) ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"4" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"4" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"4" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"4" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"4" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"4" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"4" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"4" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"23" ) ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"23" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"23" ), 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"23" ), 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"23" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"23" ), 4 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"23" ), 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"23" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"23" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L'1' ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'1', 0 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'1', 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'1', 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'1', 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'1', 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'1', 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'1', 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L'1', 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L'3' ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'3', 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'3', 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'3', 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'3', 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'3', 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'3', 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L'3', 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L'3', 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L'9' ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'9', 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'9', 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'9', 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'9', 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'9', 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'9', 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'9', 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L'9', 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"" ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"1" ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"1", 0 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"1", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"1", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"1", 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"1", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"1", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"1", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"1", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"23" ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"23", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"23", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"23", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"23", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"23", 4 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"23", 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"23", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"23", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 0, 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 1, 0 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 2, 0 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 3, 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 4, 0 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 5, 0 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 6, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 7, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 0, 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 1, 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 2, 1 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 3, 1 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 4, 1 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 5, 1 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 6, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 7, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 0, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 1, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 2, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 3, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 4, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 5, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 6, 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 7, 2 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 0, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 1, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 2, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 3, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 4, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 5, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 6, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 7, 3 ), npos ); + } + + { + boost::core::string_view sv( "123a123B123c" ); + + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789" ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789", 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789", 4 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789", 5 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789", 6 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789", 8 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789", 9 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789", 10 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789", 12 ), npos ); + } + + { + boost::core::wstring_view sv( L"123a123B123c" ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789" ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789", 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789", 4 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789", 5 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789", 6 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789", 8 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789", 9 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789", 10 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789", 12 ), npos ); + } + + { + boost::core::string_view sv( "abc1abc2abc3" ); + + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 4 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 5 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 6 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 8 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 9 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 10 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 12 ), npos ); + } + + { + boost::core::wstring_view sv( L"abc1abc2abc3" ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 4 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 5 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 6 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 8 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 9 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 10 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 12 ), npos ); + } + + { + char str[ 256 ]; + + for( int i = 0; i < 256; ++i ) + { + str[ i ] = static_cast< unsigned char >( i ); + } + + boost::core::string_view sv( str, 256 ); + + BOOST_TEST_EQ( sv.find_first_not_of( sv ), npos ); + + std::string str2( sv.data(), sv.size() ); + + for( int i = 0; i < 256; ++i ) + { + std::string str3( str2 ); + + str3[ i ] = ~str3[ i ]; + + BOOST_TEST_EQ( sv.find_first_not_of( str3 ), i ); + } + + std::reverse( str, str + 256 ); + + for( int i = 0; i < 256; ++i ) + { + std::string str3( str2 ); + + str3[ i ] = ~str3[ i ]; + + BOOST_TEST_EQ( sv.find_first_not_of( str3 ), 255 - i ); + } + } + +#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L + + { + boost::core::u8string_view sv( u8"123123" ); + + BOOST_TEST_EQ( sv.find_first_not_of( u8"" ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( u8"1" ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"1", 0 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"1", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"1", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"1", 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"1", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"1", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"1", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"1", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( u8"23" ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"23", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"23", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"23", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"23", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"23", 4 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"23", 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"23", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"23", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( u8"123", 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"123", 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"123", 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"123", 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"123", 4 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"123", 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"123", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"123", 7 ), npos ); + } + + { + boost::core::u8string_view sv( u8"123a123B123c" ); + + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789" ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789", 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789", 4 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789", 5 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789", 6 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789", 8 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789", 9 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789", 10 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789", 12 ), npos ); + } + + { + boost::core::u8string_view sv( u8"abc1abc2abc3" ); + + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 4 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 5 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 6 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 8 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 9 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 10 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 12 ), npos ); + } + +#endif + + return boost::report_errors(); +} From a51364c5d33b5effc739214b288f2244e57f6edd Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 03:33:10 +0300 Subject: [PATCH 051/258] sv_find_last_not_of_test --- include/boost/core/string_view.hpp | 30 +- test/Jamfile.v2 | 1 + test/sv_find_last_not_of_test.cpp | 573 +++++++++++++++++++++++++++++ 3 files changed, 596 insertions(+), 8 deletions(-) create mode 100644 test/sv_find_last_not_of_test.cpp diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index 1e5b879..0f32da2 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -584,31 +584,45 @@ public: BOOST_CXX14_CONSTEXPR size_type find_last_not_of( basic_string_view str, size_type pos = npos ) const BOOST_NOEXCEPT { - if( pos > size() ) + if( size() == 0 ) { - pos = size(); + return npos; } - for( std::size_t i = pos; i > 0; --i ) + if( pos > size() - 1 ) { - if( !str.contains( p_[ i - 1 ] ) ) return i - 1; + pos = size() - 1; } + do + { + if( !str.contains( p_[ pos ] ) ) return pos; + --pos; + } + while( pos != npos ); + return npos; } BOOST_CXX14_CONSTEXPR size_type find_last_not_of( Ch c, size_type pos = npos ) const BOOST_NOEXCEPT { - if( pos > size() ) + if( size() == 0 ) { - pos = size(); + return npos; } - for( std::size_t i = pos; i > 0; --i ) + if( pos > size() - 1 ) { - if( p_[ i - 1 ] != c ) return i - 1; + pos = size() - 1; } + do + { + if( p_[ pos ] != c ) return pos; + --pos; + } + while( pos != npos ); + return npos; } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 400f0d8..e9f901c 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -262,6 +262,7 @@ run sv_rfind_test.cpp ; run sv_find_first_of_test.cpp ; run sv_find_last_of_test.cpp ; run sv_find_first_not_of_test.cpp ; +run sv_find_last_not_of_test.cpp ; run sv_contains_test.cpp ; use-project /boost/core/swap : ./swap ; diff --git a/test/sv_find_last_not_of_test.cpp b/test/sv_find_last_not_of_test.cpp new file mode 100644 index 0000000..b15b3a6 --- /dev/null +++ b/test/sv_find_last_not_of_test.cpp @@ -0,0 +1,573 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +int main() +{ + std::size_t const npos = boost::core::string_view::npos; + + { + boost::core::string_view sv( "" ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view() ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view(), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "" ) ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "1" ) ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "1" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( '1' ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( '1', 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( "" ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( "1" ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "1", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( "12", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "12", 1, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( "12", 0, 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "12", 1, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( "12", 0, 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "12", 1, 2 ), npos ); + } + + { + boost::core::wstring_view sv( L"" ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view() ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view(), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"" ) ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"1" ) ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"1" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( L'1' ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L'1', 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"" ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"1" ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"1", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"12", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"12", 1, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"12", 0, 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"12", 1, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"12", 0, 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"12", 1, 2 ), npos ); + } + + { + boost::core::string_view sv( "123123" ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view(), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view(), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view(), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view(), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view(), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view(), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view(), 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view(), 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view() ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "" ), 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "" ), 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "" ) ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "1" ), 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "1" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "1" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "1" ), 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "1" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "1" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "1" ), 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "1" ), 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "1" ) ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "4" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "4" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "4" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "4" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "4" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "4" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "4" ), 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "4" ), 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "4" ) ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "23" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "23" ), 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "23" ), 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "23" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "23" ), 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "23" ), 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "23" ), 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "23" ), 7 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "23" ) ), 3 ); + + BOOST_TEST_EQ( sv.find_last_not_of( '1', 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( '1', 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( '1', 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( '1', 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( '1', 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( '1', 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( '1', 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( '1', 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( '1' ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( '3', 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( '3', 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( '3', 2 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( '3', 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( '3', 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( '3', 5 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( '3', 6 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( '3', 7 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( '3' ), 4 ); + + BOOST_TEST_EQ( sv.find_last_not_of( '9', 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( '9', 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( '9', 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( '9', 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( '9', 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( '9', 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( '9', 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( '9', 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( '9' ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( "", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( "", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( "", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( "", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( "", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( "", 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( "", 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( "" ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( "1", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "1", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( "1", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( "1", 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( "1", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( "1", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( "1", 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( "1", 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( "1" ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( "23", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( "23", 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( "23", 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( "23", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "23", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "23", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "23", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "23", 7 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "23" ), 3 ); + + BOOST_TEST_EQ( sv.find_last_not_of( "123", 0, 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 1, 0 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 2, 0 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 3, 0 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 4, 0 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 5, 0 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 6, 0 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 7, 0 ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( "123", 0, 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 1, 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 2, 1 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 3, 1 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 4, 1 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 5, 1 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 6, 1 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 7, 1 ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( "123", 0, 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 1, 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 2, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 3, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 4, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 5, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 6, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 7, 2 ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( "123", 0, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 1, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 2, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 3, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 4, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 5, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 6, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 7, 3 ), npos ); + } + + { + boost::core::wstring_view sv( L"123123" ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view(), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view(), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view(), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view(), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view(), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view(), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view(), 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view(), 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view() ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"" ), 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"" ), 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"" ) ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"1" ), 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"1" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"1" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"1" ), 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"1" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"1" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"1" ), 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"1" ), 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"1" ) ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"4" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"4" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"4" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"4" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"4" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"4" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"4" ), 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"4" ), 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"4" ) ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"23" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"23" ), 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"23" ), 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"23" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"23" ), 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"23" ), 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"23" ), 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"23" ), 7 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"23" ) ), 3 ); + + BOOST_TEST_EQ( sv.find_last_not_of( L'1', 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L'1', 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'1', 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'1', 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'1', 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'1', 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'1', 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'1', 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'1' ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( L'3', 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'3', 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'3', 2 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'3', 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'3', 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'3', 5 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'3', 6 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'3', 7 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'3' ), 4 ); + + BOOST_TEST_EQ( sv.find_last_not_of( L'9', 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'9', 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'9', 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'9', 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'9', 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'9', 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'9', 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'9', 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'9' ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"", 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"", 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"" ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"1", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"1", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"1", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"1", 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"1", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"1", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"1", 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"1", 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"1" ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"23", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"23", 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"23", 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"23", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"23", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"23", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"23", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"23", 7 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"23" ), 3 ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 0, 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 1, 0 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 2, 0 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 3, 0 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 4, 0 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 5, 0 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 6, 0 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 7, 0 ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 0, 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 1, 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 2, 1 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 3, 1 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 4, 1 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 5, 1 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 6, 1 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 7, 1 ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 0, 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 1, 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 2, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 3, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 4, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 5, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 6, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 7, 2 ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 0, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 1, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 2, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 3, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 4, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 5, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 6, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 7, 3 ), npos ); + } + + { + boost::core::string_view sv( "123a123B123c" ); + + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789", 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789", 8 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789", 9 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789", 10 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789", 12 ), 11 ); + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789" ), 11 ); + } + + { + boost::core::wstring_view sv( L"123a123B123c" ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789", 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789", 8 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789", 9 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789", 10 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789", 12 ), 11 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789" ), 11 ); + } + + { + boost::core::string_view sv( "abc1abc2abc3" ); + + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 8 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 9 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 10 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 12 ), 11 ); + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ), 11 ); + } + + { + boost::core::wstring_view sv( L"abc1abc2abc3" ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 8 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 9 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 10 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 12 ), 11 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ), 11 ); + } + + { + char str[ 256 ]; + + for( int i = 0; i < 256; ++i ) + { + str[ i ] = static_cast< unsigned char >( i ); + } + + boost::core::string_view sv( str, 256 ); + + BOOST_TEST_EQ( sv.find_last_not_of( sv ), npos ); + + std::string str2( sv.data(), sv.size() ); + + for( int i = 0; i < 256; ++i ) + { + std::string str3( str2 ); + + str3[ i ] = ~str3[ i ]; + + BOOST_TEST_EQ( sv.find_last_not_of( str3 ), i ); + } + + std::reverse( str, str + 256 ); + + for( int i = 0; i < 256; ++i ) + { + std::string str3( str2 ); + + str3[ i ] = ~str3[ i ]; + + BOOST_TEST_EQ( sv.find_last_not_of( str3 ), 255 - i ); + } + } + +#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L + + { + boost::core::u8string_view sv( u8"123123" ); + + BOOST_TEST_EQ( sv.find_last_not_of( u8"", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"", 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"", 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"" ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( u8"1", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"1", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"1", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"1", 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"1", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"1", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"1", 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"1", 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"1" ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( u8"23", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"23", 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"23", 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"23", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"23", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"23", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"23", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"23", 7 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"23" ), 3 ); + + BOOST_TEST_EQ( sv.find_last_not_of( u8"123", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"123", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"123", 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"123", 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"123", 4 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"123", 5 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"123", 6 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"123", 7 ), npos ); + } + + { + boost::core::u8string_view sv( u8"123a123B123c" ); + + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789", 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789", 8 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789", 9 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789", 10 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789", 12 ), 11 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789" ), 11 ); + } + + { + boost::core::u8string_view sv( u8"abc1abc2abc3" ); + + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 8 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 9 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 10 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 12 ), 11 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ), 11 ); + } + +#endif + + return boost::report_errors(); +} From 3d4eb536cd3d2932c7b9d2a7cdbbc947cb651d8b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 05:13:23 +0300 Subject: [PATCH 052/258] Add optimized implementation of find_last_of --- include/boost/core/string_view.hpp | 144 ++++++++++++++++++++++++----- 1 file changed, 121 insertions(+), 23 deletions(-) diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index 0f32da2..6f7f7f8 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -95,6 +95,83 @@ std::size_t find_first_of( char8_t const* p_, std::size_t n_, char8_t const* s, #endif +template BOOST_CXX14_CONSTEXPR std::size_t find_last_of( Ch const* p_, Ch const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT +{ + constexpr std::size_t npos = static_cast< std::size_t >( -1 ); + + std::size_t i = pos; + + if( n >= 16 ) + { + do + { + Ch ch = p_[ i ]; + + if( std::char_traits::find( s, n, ch ) != 0 ) return i; + + --i; + } + while( i != npos ); + } + else + { + do + { + Ch ch = p_[ i ]; + + for( std::size_t j = 0; j < n; ++j ) + { + if( s[ j ] == ch ) return i; + } + + --i; + } + while( i != npos ); + } + + return npos; +} + +#if CHAR_BIT == 8 + +BOOST_CXX14_CONSTEXPR std::size_t find_last_of( char const* p_, char const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT +{ + unsigned char table[ 256 ] = {}; + + for( std::size_t j = 0; j < n; ++j ) + { + unsigned char ch = s[ j ]; + table[ ch ] = 1; + } + + constexpr std::size_t npos = static_cast< std::size_t >( -1 ); + + std::size_t i = pos; + + do + { + unsigned char ch = p_[ i ]; + + if( table[ ch ] ) return i; + + --i; + } + while( i != npos ); + + return npos; +} + +#endif + +#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L + +std::size_t find_last_of( char8_t const* p_, char8_t const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT +{ + return detail::find_last_of( reinterpret_cast< char const* >( p_ ), reinterpret_cast< char const* >( s ), pos, n ); +} + +#endif + } // namespace detail template class basic_string_view @@ -450,8 +527,14 @@ public: pos = n - 1; } - const_reverse_iterator r = std::find( rbegin() + n - 1 - pos, rend(), c ); - return r == rend()? npos: n - 1 - ( r - rbegin() ); + do + { + if( p_[ pos ] == c ) return pos; + --pos; + } + while( pos != npos ); + + return npos; } BOOST_CXX14_CONSTEXPR size_type rfind( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT @@ -513,24 +596,7 @@ public: BOOST_CXX14_CONSTEXPR size_type find_last_of( basic_string_view str, size_type pos = npos ) const BOOST_NOEXCEPT { - if( size() == 0 ) - { - return npos; - } - - if( pos > size() - 1 ) - { - pos = size() - 1; - } - - do - { - if( str.contains( p_[ pos ] ) ) return pos; - --pos; - } - while( pos != npos ); - - return npos; + return find_last_of( str.data(), pos, str.size() ); } BOOST_CONSTEXPR size_type find_last_of( Ch c, size_type pos = npos ) const BOOST_NOEXCEPT @@ -540,12 +606,29 @@ public: BOOST_CONSTEXPR size_type find_last_of( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT { - return find_last_of( basic_string_view( s, n ), pos ); + if( n == 1 ) + { + return rfind( s[0], pos ); + } + + size_type m = size(); + + if( m == 0 ) + { + return npos; + } + + if( pos > m - 1 ) + { + pos = m - 1; + } + + return detail::find_last_of( data(), s, pos, n ); } BOOST_CONSTEXPR size_type find_last_of( Ch const* s, size_type pos = npos ) const BOOST_NOEXCEPT { - return find_last_of( basic_string_view( s ), pos ); + return find_last_of( s, pos, traits_type::length( s ) ); } // find_first_not_of @@ -645,7 +728,22 @@ public: BOOST_CONSTEXPR bool contains( Ch c ) const BOOST_NOEXCEPT { - return traits_type::find( data(), size(), c ) != 0; + Ch const* p = data(); + size_type n = size(); + + if( n >= 16 ) + { + return traits_type::find( p, n, c ) != 0; + } + else + { + for( size_type i = 0; i < n; ++i ) + { + if( p[ i ] == c ) return true; + } + + return false; + } } BOOST_CONSTEXPR bool contains( Ch const* s ) const BOOST_NOEXCEPT From b9f1b9f39ac8ff5a16ffb85762c8ab7f96c7b7e0 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 06:40:59 +0300 Subject: [PATCH 053/258] Add optimized implementation of find_first_not_of --- include/boost/core/string_view.hpp | 101 ++++++++++++++++++++++++----- 1 file changed, 86 insertions(+), 15 deletions(-) diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index 6f7f7f8..bf29541 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -97,7 +97,7 @@ std::size_t find_first_of( char8_t const* p_, std::size_t n_, char8_t const* s, template BOOST_CXX14_CONSTEXPR std::size_t find_last_of( Ch const* p_, Ch const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT { - constexpr std::size_t npos = static_cast< std::size_t >( -1 ); + std::size_t const npos = static_cast< std::size_t >( -1 ); std::size_t i = pos; @@ -144,7 +144,7 @@ BOOST_CXX14_CONSTEXPR std::size_t find_last_of( char const* p_, char const* s, s table[ ch ] = 1; } - constexpr std::size_t npos = static_cast< std::size_t >( -1 ); + std::size_t const npos = static_cast< std::size_t >( -1 ); std::size_t i = pos; @@ -172,6 +172,79 @@ std::size_t find_last_of( char8_t const* p_, char8_t const* s, std::size_t pos, #endif +template struct sv_to_uchar +{ + typedef Ch type; +}; + +template<> struct sv_to_uchar +{ + typedef unsigned char type; +}; + +template BOOST_CXX14_CONSTEXPR std::size_t find_first_not_of( Ch const* p_, std::size_t n_, Ch const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT +{ + typedef typename sv_to_uchar::type UCh; + + unsigned char table[ 256 ] = {}; + + bool use_table = true; + + for( std::size_t j = 0; j < n; ++j ) + { + UCh ch = s[ j ]; + + if( ch >= 0 && ch < 256 ) + { + table[ ch ] = 1; + } + else + { + use_table = false; + break; + } + } + + if( use_table ) + { + for( std::size_t i = pos; i < n_; ++i ) + { + UCh ch = p_[ i ]; + if( !( ch >= 0 && ch < 256 && table[ ch ] ) ) return i; + } + } + else if( n >= 16 ) + { + for( std::size_t i = pos; i < n_; ++i ) + { + Ch ch = p_[ i ]; + if( std::char_traits::find( s, n, ch ) == 0 ) return i; + } + } + else + { + for( std::size_t i = pos; i < n_; ++i ) + { + Ch ch = p_[ i ]; + + bool r = false; + + for( std::size_t j = 0; j < n; ++j ) + { + if( s[ j ] == ch ) + { + r = true; + break; + } + } + + if( !r ) return i; + } + } + + return static_cast( -1 ); +} + } // namespace detail template class basic_string_view @@ -604,7 +677,7 @@ public: return rfind( c, pos ); } - BOOST_CONSTEXPR size_type find_last_of( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT + BOOST_CXX14_CONSTEXPR size_type find_last_of( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT { if( n == 1 ) { @@ -626,7 +699,7 @@ public: return detail::find_last_of( data(), s, pos, n ); } - BOOST_CONSTEXPR size_type find_last_of( Ch const* s, size_type pos = npos ) const BOOST_NOEXCEPT + BOOST_CXX14_CONSTEXPR size_type find_last_of( Ch const* s, size_type pos = npos ) const BOOST_NOEXCEPT { return find_last_of( s, pos, traits_type::length( s ) ); } @@ -635,12 +708,7 @@ public: BOOST_CXX14_CONSTEXPR size_type find_first_not_of( basic_string_view str, size_type pos = 0 ) const BOOST_NOEXCEPT { - for( std::size_t i = pos; i < n_; ++i ) - { - if( !str.contains( p_[ i ] ) ) return i; - } - - return npos; + return find_first_not_of( str.data(), pos, str.size() ); } BOOST_CXX14_CONSTEXPR size_type find_first_not_of( Ch c, size_type pos = 0 ) const BOOST_NOEXCEPT @@ -653,14 +721,17 @@ public: return npos; } - BOOST_CONSTEXPR size_type find_first_not_of( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT + BOOST_CXX14_CONSTEXPR size_type find_first_not_of( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT { - return find_first_not_of( basic_string_view( s, n ), pos ); + if( pos >= size() ) return npos; + if( n == 1 ) return find_first_not_of( s[0], pos ); + + return detail::find_first_not_of( data(), size(), s, pos, n ); } - BOOST_CONSTEXPR size_type find_first_not_of( Ch const* s, size_type pos = 0 ) const BOOST_NOEXCEPT + BOOST_CXX14_CONSTEXPR size_type find_first_not_of( Ch const* s, size_type pos = 0 ) const BOOST_NOEXCEPT { - return find_first_not_of( basic_string_view( s ), pos ); + return find_first_not_of( s, pos, traits_type::length( s ) ); } // find_last_not_of @@ -726,7 +797,7 @@ public: return find( sv ) != npos; } - BOOST_CONSTEXPR bool contains( Ch c ) const BOOST_NOEXCEPT + BOOST_CXX14_CONSTEXPR bool contains( Ch c ) const BOOST_NOEXCEPT { Ch const* p = data(); size_type n = size(); From 969a201c7596e6197b04f48be1ed8886168e2261 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 06:43:48 +0300 Subject: [PATCH 054/258] Update implementation of find_first_of --- include/boost/core/string_view.hpp | 83 ++++++++++++++---------------- 1 file changed, 40 insertions(+), 43 deletions(-) diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index bf29541..9be8dc2 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -37,9 +37,48 @@ namespace core namespace detail { +template struct sv_to_uchar +{ + typedef Ch type; +}; + +template<> struct sv_to_uchar +{ + typedef unsigned char type; +}; + template BOOST_CXX14_CONSTEXPR std::size_t find_first_of( Ch const* p_, std::size_t n_, Ch const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT { - if( n >= 16 ) + typedef typename sv_to_uchar::type UCh; + + unsigned char table[ 256 ] = {}; + + bool use_table = true; + + for( std::size_t j = 0; j < n; ++j ) + { + UCh ch = s[ j ]; + + if( ch >= 0 && ch < 256 ) + { + table[ ch ] = 1; + } + else + { + use_table = false; + break; + } + } + + if( use_table ) + { + for( std::size_t i = pos; i < n_; ++i ) + { + UCh ch = p_[ i ]; + if( ch >= 0 && ch < 256 && table[ ch ] ) return i; + } + } + else if( n >= 16 ) { for( std::size_t i = pos; i < n_; ++i ) { @@ -63,38 +102,6 @@ template BOOST_CXX14_CONSTEXPR std::size_t find_first_of( Ch const* p_ return static_cast( -1 ); } -#if CHAR_BIT == 8 - -BOOST_CXX14_CONSTEXPR std::size_t find_first_of( char const* p_, std::size_t n_, char const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT -{ - unsigned char table[ 256 ] = {}; - - for( std::size_t j = 0; j < n; ++j ) - { - unsigned char ch = s[ j ]; - table[ ch ] = 1; - } - - for( std::size_t i = pos; i < n_; ++i ) - { - unsigned char ch = p_[ i ]; - if( table[ ch ] ) return i; - } - - return static_cast( -1 ); -} - -#endif - -#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L - -std::size_t find_first_of( char8_t const* p_, std::size_t n_, char8_t const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT -{ - return detail::find_first_of( reinterpret_cast< char const* >( p_ ), n_, reinterpret_cast< char const* >( s ), pos, n ); -} - -#endif - template BOOST_CXX14_CONSTEXPR std::size_t find_last_of( Ch const* p_, Ch const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT { std::size_t const npos = static_cast< std::size_t >( -1 ); @@ -172,16 +179,6 @@ std::size_t find_last_of( char8_t const* p_, char8_t const* s, std::size_t pos, #endif -template struct sv_to_uchar -{ - typedef Ch type; -}; - -template<> struct sv_to_uchar -{ - typedef unsigned char type; -}; - template BOOST_CXX14_CONSTEXPR std::size_t find_first_not_of( Ch const* p_, std::size_t n_, Ch const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT { typedef typename sv_to_uchar::type UCh; From b251310a8f39cf852ac195c8ec846d57334b4aaa Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 06:47:39 +0300 Subject: [PATCH 055/258] Update implementation of find_last_of --- include/boost/core/string_view.hpp | 75 ++++++++++++++---------------- 1 file changed, 34 insertions(+), 41 deletions(-) diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index 9be8dc2..5ea29c2 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -104,11 +104,44 @@ template BOOST_CXX14_CONSTEXPR std::size_t find_first_of( Ch const* p_ template BOOST_CXX14_CONSTEXPR std::size_t find_last_of( Ch const* p_, Ch const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT { + typedef typename sv_to_uchar::type UCh; + + unsigned char table[ 256 ] = {}; + + bool use_table = true; + + for( std::size_t j = 0; j < n; ++j ) + { + UCh ch = s[ j ]; + + if( ch >= 0 && ch < 256 ) + { + table[ ch ] = 1; + } + else + { + use_table = false; + break; + } + } + std::size_t const npos = static_cast< std::size_t >( -1 ); std::size_t i = pos; - if( n >= 16 ) + if( use_table ) + { + do + { + UCh ch = p_[ i ]; + + if( ch >= 0 && ch < 256 && table[ ch ] ) return i; + + --i; + } + while( i != npos ); + } + else if( n >= 16 ) { do { @@ -139,46 +172,6 @@ template BOOST_CXX14_CONSTEXPR std::size_t find_last_of( Ch const* p_, return npos; } -#if CHAR_BIT == 8 - -BOOST_CXX14_CONSTEXPR std::size_t find_last_of( char const* p_, char const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT -{ - unsigned char table[ 256 ] = {}; - - for( std::size_t j = 0; j < n; ++j ) - { - unsigned char ch = s[ j ]; - table[ ch ] = 1; - } - - std::size_t const npos = static_cast< std::size_t >( -1 ); - - std::size_t i = pos; - - do - { - unsigned char ch = p_[ i ]; - - if( table[ ch ] ) return i; - - --i; - } - while( i != npos ); - - return npos; -} - -#endif - -#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L - -std::size_t find_last_of( char8_t const* p_, char8_t const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT -{ - return detail::find_last_of( reinterpret_cast< char const* >( p_ ), reinterpret_cast< char const* >( s ), pos, n ); -} - -#endif - template BOOST_CXX14_CONSTEXPR std::size_t find_first_not_of( Ch const* p_, std::size_t n_, Ch const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT { typedef typename sv_to_uchar::type UCh; From b70bbf14db33881531ab3112e8d0a6741f80a756 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 06:52:08 +0300 Subject: [PATCH 056/258] Update sv_find_first_of_test --- test/sv_find_first_of_test.cpp | 40 ++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/sv_find_first_of_test.cpp b/test/sv_find_first_of_test.cpp index 92e4188..728d4f6 100644 --- a/test/sv_find_first_of_test.cpp +++ b/test/sv_find_first_of_test.cpp @@ -305,6 +305,46 @@ int main() BOOST_TEST_EQ( sv.find_first_of( L"123", 7, 3 ), npos ); } + { + boost::core::wstring_view sv( L"\x101\x102\x103\x101\x102\x103" ); + + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 1, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 2, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 3, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 4, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 5, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 6, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 7, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 0, 1 ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 1, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 2, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 3, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 4, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 5, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 6, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 7, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 0, 2 ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 1, 2 ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 2, 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 3, 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 4, 2 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 5, 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 6, 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 7, 2 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 0, 3 ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 1, 3 ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 2, 3 ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 3, 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 4, 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 5, 3 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 6, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 7, 3 ), npos ); + } + { boost::core::string_view sv( "abc1abc2abc3" ); From 63f3a97a151581dbd7455e48c47ffd9f98723022 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 06:54:23 +0300 Subject: [PATCH 057/258] Update find_last_of_test --- test/sv_find_last_of_test.cpp | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/sv_find_last_of_test.cpp b/test/sv_find_last_of_test.cpp index 2e85476..2008ab9 100644 --- a/test/sv_find_last_of_test.cpp +++ b/test/sv_find_last_of_test.cpp @@ -323,6 +323,46 @@ int main() BOOST_TEST_EQ( sv.find_last_of( L"123", 7, 3 ), 5 ); } + { + boost::core::wstring_view sv( L"\x101\x102\x103\x101\x102\x103" ); + + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 1, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 2, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 3, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 4, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 5, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 6, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 7, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 0, 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 1, 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 2, 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 3, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 4, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 5, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 6, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 7, 1 ), 3 ); + + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 0, 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 1, 2 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 2, 2 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 3, 2 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 4, 2 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 5, 2 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 6, 2 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 7, 2 ), 4 ); + + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 0, 3 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 1, 3 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 2, 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 3, 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 4, 3 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 5, 3 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 6, 3 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 7, 3 ), 5 ); + } + { boost::core::string_view sv( "abc1abc2abc3" ); From 9f2ec3bfca3a13ce82aa7253d1add0bb300d0c09 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 06:58:11 +0300 Subject: [PATCH 058/258] Update find_first_not_of_test --- test/sv_find_first_not_of_test.cpp | 40 ++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/sv_find_first_not_of_test.cpp b/test/sv_find_first_not_of_test.cpp index e0258b5..2998e03 100644 --- a/test/sv_find_first_not_of_test.cpp +++ b/test/sv_find_first_not_of_test.cpp @@ -373,6 +373,46 @@ int main() BOOST_TEST_EQ( sv.find_first_not_of( L"123", 7, 3 ), npos ); } + { + boost::core::wstring_view sv( L"\x101\x102\x103\x101\x102\x103" ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 0, 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 1, 0 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 2, 0 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 3, 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 4, 0 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 5, 0 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 6, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 7, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 0, 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 1, 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 2, 1 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 3, 1 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 4, 1 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 5, 1 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 6, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 7, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 0, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 1, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 2, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 3, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 4, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 5, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 6, 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 7, 2 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 0, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 1, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 2, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 3, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 4, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 5, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 6, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 7, 3 ), npos ); + } + { boost::core::string_view sv( "123a123B123c" ); From 408cd96595a8d11ed2965b7b433a32c02ee3f590 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 07:00:32 +0300 Subject: [PATCH 059/258] Update sv_find_last_not_of_test --- test/sv_find_last_not_of_test.cpp | 40 +++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/sv_find_last_not_of_test.cpp b/test/sv_find_last_not_of_test.cpp index b15b3a6..348eb29 100644 --- a/test/sv_find_last_not_of_test.cpp +++ b/test/sv_find_last_not_of_test.cpp @@ -373,6 +373,46 @@ int main() BOOST_TEST_EQ( sv.find_last_not_of( L"123", 7, 3 ), npos ); } + { + boost::core::wstring_view sv( L"\x101\x102\x103\x101\x102\x103" ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 0, 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 1, 0 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 2, 0 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 3, 0 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 4, 0 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 5, 0 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 6, 0 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 7, 0 ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 0, 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 1, 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 2, 1 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 3, 1 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 4, 1 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 5, 1 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 6, 1 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 7, 1 ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 0, 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 1, 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 2, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 3, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 4, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 5, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 6, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 7, 2 ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 0, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 1, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 2, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 3, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 4, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 5, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 6, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 7, 3 ), npos ); + } + { boost::core::string_view sv( "123a123B123c" ); From b01f2fe4d28414964c7c7d27c51308846f72ed7b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 07:08:48 +0300 Subject: [PATCH 060/258] Add optimized implementation of find_last_not_of --- include/boost/core/string_view.hpp | 130 +++++++++++++++++++++++------ 1 file changed, 105 insertions(+), 25 deletions(-) diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index 5ea29c2..8540f0c 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -235,6 +235,84 @@ template BOOST_CXX14_CONSTEXPR std::size_t find_first_not_of( Ch const return static_cast( -1 ); } +template BOOST_CXX14_CONSTEXPR std::size_t find_last_not_of( Ch const* p_, Ch const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT +{ + typedef typename sv_to_uchar::type UCh; + + unsigned char table[ 256 ] = {}; + + bool use_table = true; + + for( std::size_t j = 0; j < n; ++j ) + { + UCh ch = s[ j ]; + + if( ch >= 0 && ch < 256 ) + { + table[ ch ] = 1; + } + else + { + use_table = false; + break; + } + } + + std::size_t const npos = static_cast< std::size_t >( -1 ); + + std::size_t i = pos; + + if( use_table ) + { + do + { + UCh ch = p_[ i ]; + + if( !( ch >= 0 && ch < 256 && table[ ch ] ) ) return i; + + --i; + } + while( i != npos ); + } + else if( n >= 16 ) + { + do + { + Ch ch = p_[ i ]; + + if( std::char_traits::find( s, n, ch ) == 0 ) return i; + + --i; + } + while( i != npos ); + } + else + { + do + { + Ch ch = p_[ i ]; + + bool r = false; + + for( std::size_t j = 0; j < n; ++j ) + { + if( s[ j ] == ch ) + { + r = true; + break; + } + } + + if( !r ) return i; + + --i; + } + while( i != npos ); + } + + return npos; +} + } // namespace detail template class basic_string_view @@ -728,36 +806,21 @@ public: BOOST_CXX14_CONSTEXPR size_type find_last_not_of( basic_string_view str, size_type pos = npos ) const BOOST_NOEXCEPT { - if( size() == 0 ) - { - return npos; - } - - if( pos > size() - 1 ) - { - pos = size() - 1; - } - - do - { - if( !str.contains( p_[ pos ] ) ) return pos; - --pos; - } - while( pos != npos ); - - return npos; + return find_last_not_of( str.data(), pos, str.size() ); } BOOST_CXX14_CONSTEXPR size_type find_last_not_of( Ch c, size_type pos = npos ) const BOOST_NOEXCEPT { - if( size() == 0 ) + size_type m = size(); + + if( m == 0 ) { return npos; } - if( pos > size() - 1 ) + if( pos > m - 1 ) { - pos = size() - 1; + pos = m - 1; } do @@ -770,14 +833,31 @@ public: return npos; } - BOOST_CONSTEXPR size_type find_last_not_of( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT + BOOST_CXX14_CONSTEXPR size_type find_last_not_of( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT { - return find_last_not_of( basic_string_view( s, n ), pos ); + if( n == 1 ) + { + return find_last_not_of( s[0], pos ); + } + + size_type m = size(); + + if( m == 0 ) + { + return npos; + } + + if( pos > m - 1 ) + { + pos = m - 1; + } + + return detail::find_last_not_of( data(), s, pos, n ); } - BOOST_CONSTEXPR size_type find_last_not_of( Ch const* s, size_type pos = npos ) const BOOST_NOEXCEPT + BOOST_CXX14_CONSTEXPR size_type find_last_not_of( Ch const* s, size_type pos = npos ) const BOOST_NOEXCEPT { - return find_last_not_of( basic_string_view( s ), pos ); + return find_last_not_of( s, pos, traits_type::length( s ) ); } // contains From 62e9d9b8686c96a59ea50f6044fe6ffeade9216f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 07:13:56 +0300 Subject: [PATCH 061/258] Update tests --- test/sv_find_first_not_of_test.cpp | 35 ++++++++++++++++++++++++++++++ test/sv_find_first_of_test.cpp | 25 +++++++++++++++++++++ test/sv_find_last_not_of_test.cpp | 35 ++++++++++++++++++++++++++++++ test/sv_find_last_of_test.cpp | 25 +++++++++++++++++++++ 4 files changed, 120 insertions(+) diff --git a/test/sv_find_first_not_of_test.cpp b/test/sv_find_first_not_of_test.cpp index 2998e03..a32a6e1 100644 --- a/test/sv_find_first_not_of_test.cpp +++ b/test/sv_find_first_not_of_test.cpp @@ -524,6 +524,41 @@ int main() } } + { + wchar_t str[ 256 ]; + + for( int i = 0; i < 256; ++i ) + { + str[ i ] = static_cast< wchar_t >( 0x100 + i ); + } + + boost::core::wstring_view sv( str, 256 ); + + BOOST_TEST_EQ( sv.find_first_not_of( sv ), npos ); + + std::wstring str2( sv.data(), sv.size() ); + + for( int i = 0; i < 256; ++i ) + { + std::wstring str3( str2 ); + + str3[ i ] = ~str3[ i ]; + + BOOST_TEST_EQ( sv.find_first_not_of( str3 ), i ); + } + + std::reverse( str, str + 256 ); + + for( int i = 0; i < 256; ++i ) + { + std::wstring str3( str2 ); + + str3[ i ] = ~str3[ i ]; + + BOOST_TEST_EQ( sv.find_first_not_of( str3 ), 255 - i ); + } + } + #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L { diff --git a/test/sv_find_first_of_test.cpp b/test/sv_find_first_of_test.cpp index 728d4f6..f5704c0 100644 --- a/test/sv_find_first_of_test.cpp +++ b/test/sv_find_first_of_test.cpp @@ -446,6 +446,31 @@ int main() } } + { + wchar_t str[ 256 ]; + + for( int i = 0; i < 256; ++i ) + { + str[ i ] = static_cast< wchar_t >( 0x100 + i ); + } + + boost::core::wstring_view sv( str, 256 ); + + for( int i = 0; i < 256; ++i ) + { + std::wstring needle( 12, static_cast< wchar_t >( 0x100 + i ) ); + BOOST_TEST_EQ( sv.find_first_of( needle ), i ); + } + + std::reverse( str, str + 256 ); + + for( int i = 0; i < 256; ++i ) + { + std::wstring needle( 12, static_cast< wchar_t >( 0x100 + i ) ); + BOOST_TEST_EQ( sv.find_first_of( needle ), 255 - i ); + } + } + #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L { diff --git a/test/sv_find_last_not_of_test.cpp b/test/sv_find_last_not_of_test.cpp index 348eb29..96a71cd 100644 --- a/test/sv_find_last_not_of_test.cpp +++ b/test/sv_find_last_not_of_test.cpp @@ -524,6 +524,41 @@ int main() } } + { + wchar_t str[ 256 ]; + + for( int i = 0; i < 256; ++i ) + { + str[ i ] = static_cast< wchar_t >( 0x100 + i ); + } + + boost::core::wstring_view sv( str, 256 ); + + BOOST_TEST_EQ( sv.find_first_not_of( sv ), npos ); + + std::wstring str2( sv.data(), sv.size() ); + + for( int i = 0; i < 256; ++i ) + { + std::wstring str3( str2 ); + + str3[ i ] = ~str3[ i ]; + + BOOST_TEST_EQ( sv.find_first_not_of( str3 ), i ); + } + + std::reverse( str, str + 256 ); + + for( int i = 0; i < 256; ++i ) + { + std::wstring str3( str2 ); + + str3[ i ] = ~str3[ i ]; + + BOOST_TEST_EQ( sv.find_first_not_of( str3 ), 255 - i ); + } + } + #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L { diff --git a/test/sv_find_last_of_test.cpp b/test/sv_find_last_of_test.cpp index 2008ab9..5cc0624 100644 --- a/test/sv_find_last_of_test.cpp +++ b/test/sv_find_last_of_test.cpp @@ -464,6 +464,31 @@ int main() } } + { + wchar_t str[ 256 ]; + + for( int i = 0; i < 256; ++i ) + { + str[ i ] = static_cast< wchar_t >( 0x100 + i ); + } + + boost::core::wstring_view sv( str, 256 ); + + for( int i = 0; i < 256; ++i ) + { + std::wstring needle( 12, static_cast< wchar_t >( 0x100 + i ) ); + BOOST_TEST_EQ( sv.find_first_of( needle ), i ); + } + + std::reverse( str, str + 256 ); + + for( int i = 0; i < 256; ++i ) + { + std::wstring needle( 12, static_cast< wchar_t >( 0x100 + i ) ); + BOOST_TEST_EQ( sv.find_first_of( needle ), 255 - i ); + } + } + #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L { From db15c7419dcdf0886d350bd25f77dad72491bdad Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 16:50:14 +0300 Subject: [PATCH 062/258] Add sv_eq_test --- include/boost/core/string_view.hpp | 7 +++ test/Jamfile.v2 | 1 + test/sv_eq_test.cpp | 84 ++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+) create mode 100644 test/sv_eq_test.cpp diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index 8540f0c..23c2d50 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -26,6 +26,7 @@ #include #include #include +#include #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) # include #endif @@ -905,6 +906,12 @@ public: } }; +template std::basic_ostream& operator<<( std::basic_ostream& os, basic_string_view str ) +{ + os.write( str.data(), str.size() ); + return os; +} + #if defined(BOOST_NO_CXX17_INLINE_VARIABLES) template BOOST_CONSTEXPR_OR_CONST std::size_t basic_string_view::npos; #endif diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index e9f901c..170b53f 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -264,6 +264,7 @@ run sv_find_last_of_test.cpp ; run sv_find_first_not_of_test.cpp ; run sv_find_last_not_of_test.cpp ; run sv_contains_test.cpp ; +run sv_eq_test.cpp ; use-project /boost/core/swap : ./swap ; build-project ./swap ; diff --git a/test/sv_eq_test.cpp b/test/sv_eq_test.cpp new file mode 100644 index 0000000..a71e125 --- /dev/null +++ b/test/sv_eq_test.cpp @@ -0,0 +1,84 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) +# include +#endif + +#define TEST_EQ(x, y) BOOST_TEST_EQ(x, y); BOOST_TEST_NOT((x) != (y)) +#define TEST_NE(x, y) BOOST_TEST_NE(x, y); BOOST_TEST_NOT((x) == (y)) + +int main() +{ + std::size_t const npos = boost::core::string_view::npos; + + { + boost::core::string_view sv1( "" ); + boost::core::string_view sv2( "" ); + boost::core::string_view sv3( "123" ); + boost::core::string_view sv4( "123" ); + boost::core::string_view sv5( "12345" ); + boost::core::string_view sv6( "12345" ); + + TEST_EQ( sv1, sv1 ); + TEST_EQ( sv1, sv2 ); + TEST_NE( sv1, sv3 ); + TEST_NE( sv1, sv5 ); + + TEST_EQ( sv3, sv3 ); + TEST_EQ( sv3, sv4 ); + TEST_NE( sv3, sv1 ); + TEST_NE( sv3, sv5 ); + + TEST_EQ( sv5, sv5 ); + TEST_EQ( sv5, sv6 ); + TEST_NE( sv5, sv1 ); + TEST_NE( sv5, sv3 ); + + BOOST_TEST_EQ( sv1, std::string( "" ) ); + BOOST_TEST_EQ( std::string( "" ), sv1 ); + + BOOST_TEST_NE( sv1, std::string( "1" ) ); + BOOST_TEST_NE( std::string( "1" ), sv1 ); + + BOOST_TEST_EQ( sv3, std::string( "123" ) ); + BOOST_TEST_EQ( std::string( "123" ), sv3 ); + + BOOST_TEST_NE( sv3, std::string( "122" ) ); + BOOST_TEST_NE( std::string( "122" ), sv3 ); + + BOOST_TEST_EQ( sv1, "" ); + BOOST_TEST_EQ( "", sv1 ); + + BOOST_TEST_NE( sv1, "1" ); + BOOST_TEST_NE( "1", sv1 ); + + BOOST_TEST_EQ( sv3, "123" ); + BOOST_TEST_EQ( "123", sv3 ); + + BOOST_TEST_NE( sv3, "122" ); + BOOST_TEST_NE( "122", sv3 ); + +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) + + BOOST_TEST_EQ( sv1, std::string_view( "" ) ); + BOOST_TEST_EQ( std::string_view( "" ), sv1 ); + + BOOST_TEST_NE( sv1, std::string_view( "1" ) ); + BOOST_TEST_NE( std::string_view( "1" ), sv1 ); + + BOOST_TEST_EQ( sv3, std::string_view( "123" ) ); + BOOST_TEST_EQ( std::string_view( "123" ), sv3 ); + + BOOST_TEST_NE( sv3, std::string_view( "122" ) ); + BOOST_TEST_NE( std::string_view( "122" ), sv3 ); + +#endif + } + + return boost::report_errors(); +} From 5c82e38c93fb8022400050a20bec94bd56c9dcbe Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 16:55:33 +0300 Subject: [PATCH 063/258] Add other relational operators; update sv_eq_test --- include/boost/core/string_view.hpp | 20 ++++++++++++++++++++ test/sv_eq_test.cpp | 14 ++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index 23c2d50..0ee3916 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -904,6 +904,26 @@ public: { return sv1.compare( sv2 ) != 0; } + + BOOST_CXX14_CONSTEXPR friend bool operator<( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) < 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator<=( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) <= 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator>( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) > 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator>=( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) >= 0; + } }; template std::basic_ostream& operator<<( std::basic_ostream& os, basic_string_view str ) diff --git a/test/sv_eq_test.cpp b/test/sv_eq_test.cpp index a71e125..ba32d13 100644 --- a/test/sv_eq_test.cpp +++ b/test/sv_eq_test.cpp @@ -9,8 +9,18 @@ # include #endif -#define TEST_EQ(x, y) BOOST_TEST_EQ(x, y); BOOST_TEST_NOT((x) != (y)) -#define TEST_NE(x, y) BOOST_TEST_NE(x, y); BOOST_TEST_NOT((x) == (y)) +#define TEST_EQ(x, y) \ + BOOST_TEST_EQ(x, y); \ + BOOST_TEST_NOT((x) != (y)); \ + BOOST_TEST_LE(x, y); \ + BOOST_TEST_GE(x, y); \ + BOOST_TEST_NOT((x) < (y)); \ + BOOST_TEST_NOT((x) > (y)) + +#define TEST_NE(x, y) \ + BOOST_TEST_NE(x, y); \ + BOOST_TEST_NOT((x) == (y)); \ + BOOST_TEST((x) < (y) || (x) > (y)); int main() { From a121d5a000c2fd6616182bf1b8fef131262e0a69 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 17:09:23 +0300 Subject: [PATCH 064/258] Add sv_lt_test --- test/Jamfile.v2 | 1 + test/sv_lt_test.cpp | 95 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 test/sv_lt_test.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 170b53f..7286df2 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -265,6 +265,7 @@ run sv_find_first_not_of_test.cpp ; run sv_find_last_not_of_test.cpp ; run sv_contains_test.cpp ; run sv_eq_test.cpp ; +run sv_lt_test.cpp ; use-project /boost/core/swap : ./swap ; build-project ./swap ; diff --git a/test/sv_lt_test.cpp b/test/sv_lt_test.cpp new file mode 100644 index 0000000..e86148b --- /dev/null +++ b/test/sv_lt_test.cpp @@ -0,0 +1,95 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) +# include +#endif + +#define TEST_LT(x, y) \ + BOOST_TEST_LT(x, y); \ + BOOST_TEST_LE(x, y); \ + BOOST_TEST_NE(x, y); \ + BOOST_TEST_NOT((x) == (y)); \ + BOOST_TEST_NOT((x) >= (y)); \ + BOOST_TEST_NOT((x) > (y)); \ + BOOST_TEST_GT(y, x); \ + BOOST_TEST_GE(y, x); \ + BOOST_TEST_NOT((y) < (x)); \ + BOOST_TEST_NOT((y) <= (x)); + +int main() +{ + std::size_t const npos = boost::core::string_view::npos; + + { + boost::core::string_view sv0( "" ); + boost::core::string_view sv1( "12" ); + boost::core::string_view sv2( "122" ); + boost::core::string_view sv3( "123" ); + boost::core::string_view sv4( "124" ); + boost::core::string_view sv5( "1234" ); + + TEST_LT( sv0, sv1 ); + TEST_LT( sv1, sv2 ); + TEST_LT( sv2, sv3 ); + TEST_LT( sv3, sv4 ); + TEST_LT( sv3, sv5 ); + TEST_LT( sv5, sv4 ); + + TEST_LT( sv0, std::string( "12" ) ); + TEST_LT( sv1, std::string( "122" ) ); + TEST_LT( sv2, std::string( "123" ) ); + TEST_LT( sv3, std::string( "124" ) ); + TEST_LT( sv3, std::string( "1234" ) ); + TEST_LT( sv5, std::string( "124" ) ); + + TEST_LT( sv0, "12" ); + TEST_LT( sv1, "122" ); + TEST_LT( sv2, "123" ); + TEST_LT( sv3, "124" ); + TEST_LT( sv3, "1234" ); + TEST_LT( sv5, "124" ); + +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) + + TEST_LT( sv0, std::string_view( "12" ) ); + TEST_LT( sv1, std::string_view( "122" ) ); + TEST_LT( sv2, std::string_view( "123" ) ); + TEST_LT( sv3, std::string_view( "124" ) ); + TEST_LT( sv3, std::string_view( "1234" ) ); + TEST_LT( sv5, std::string_view( "124" ) ); + +#endif + + TEST_LT( std::string( "" ), sv1 ); + TEST_LT( std::string( "12" ), sv2 ); + TEST_LT( std::string( "122" ), sv3 ); + TEST_LT( std::string( "123" ), sv4 ); + TEST_LT( std::string( "123" ), sv5 ); + TEST_LT( std::string( "1234" ), sv4 ); + + TEST_LT( "", sv1 ); + TEST_LT( "12", sv2 ); + TEST_LT( "122", sv3 ); + TEST_LT( "123", sv4 ); + TEST_LT( "123", sv5 ); + TEST_LT( "1234", sv4 ); + +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) + + TEST_LT( std::string_view( "" ), sv1 ); + TEST_LT( std::string_view( "12" ), sv2 ); + TEST_LT( std::string_view( "122" ), sv3 ); + TEST_LT( std::string_view( "123" ), sv4 ); + TEST_LT( std::string_view( "123" ), sv5 ); + TEST_LT( std::string_view( "1234" ), sv4 ); + +#endif + } + + return boost::report_errors(); +} From e9ffc4336cc9601031693604541d8b7465efe288 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 17:10:52 +0300 Subject: [PATCH 065/258] Remove unused npos variables --- test/sv_eq_test.cpp | 2 -- test/sv_lt_test.cpp | 2 -- 2 files changed, 4 deletions(-) diff --git a/test/sv_eq_test.cpp b/test/sv_eq_test.cpp index ba32d13..3511a14 100644 --- a/test/sv_eq_test.cpp +++ b/test/sv_eq_test.cpp @@ -24,8 +24,6 @@ int main() { - std::size_t const npos = boost::core::string_view::npos; - { boost::core::string_view sv1( "" ); boost::core::string_view sv2( "" ); diff --git a/test/sv_lt_test.cpp b/test/sv_lt_test.cpp index e86148b..0c78b91 100644 --- a/test/sv_lt_test.cpp +++ b/test/sv_lt_test.cpp @@ -23,8 +23,6 @@ int main() { - std::size_t const npos = boost::core::string_view::npos; - { boost::core::string_view sv0( "" ); boost::core::string_view sv1( "12" ); From c8b860704e409a3c14f32dc85293cae9f1ac1b8d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 17:36:06 +0300 Subject: [PATCH 066/258] Add sv_stream_insert_test --- include/boost/core/string_view.hpp | 33 ++++++++- test/Jamfile.v2 | 1 + test/sv_stream_insert_test.cpp | 111 +++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 test/sv_stream_insert_test.cpp diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index 0ee3916..d9704bd 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -928,7 +928,38 @@ public: template std::basic_ostream& operator<<( std::basic_ostream& os, basic_string_view str ) { - os.write( str.data(), str.size() ); + Ch const* p = str.data(); + std::size_t n = str.size(); + + if( n == 0 ) + { + os << ""; + } + else + { + std::size_t m = os.width(); + + if( n >= m ) + { + os.write( p, n ); + } + else if( ( os.flags() & std::ios_base::adjustfield ) == std::ios_base::left ) + { + os.write( p, n - 1 ); + + os.width( m - n + 1 ); + os << p[ n-1 ]; + } + else + { + os.width( m - n + 1 ); + os << p[0]; + + os.write( p + 1, n - 1 ); + } + } + + os.width( 0 ); return os; } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 7286df2..b6c89b5 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -266,6 +266,7 @@ run sv_find_last_not_of_test.cpp ; run sv_contains_test.cpp ; run sv_eq_test.cpp ; run sv_lt_test.cpp ; +run sv_stream_insert_test.cpp ; use-project /boost/core/swap : ./swap ; build-project ./swap ; diff --git a/test/sv_stream_insert_test.cpp b/test/sv_stream_insert_test.cpp new file mode 100644 index 0000000..cebdf01 --- /dev/null +++ b/test/sv_stream_insert_test.cpp @@ -0,0 +1,111 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +int main() +{ + using boost::core::string_view; + + { + std::ostringstream os; + + os << string_view( "" ); + + BOOST_TEST_EQ( os.str(), std::string( "" ) ); + } + + { + std::ostringstream os; + + os << string_view( "123" ); + + BOOST_TEST_EQ( os.str(), std::string( "123" ) ); + } + + { + std::ostringstream os; + + os << std::setw( 5 ) << string_view( "" ); + + BOOST_TEST_EQ( os.str(), std::string( " " ) ); + } + + { + std::ostringstream os; + + os << std::setfill( '-' ) << std::setw( 5 ) << string_view( "" ); + + BOOST_TEST_EQ( os.str(), std::string( "-----" ) ); + } + + { + std::ostringstream os; + + os << std::setw( 5 ) << string_view( "123" ); + + BOOST_TEST_EQ( os.str(), std::string( " 123" ) ); + } + + { + std::ostringstream os; + + os << std::left << std::setw( 5 ) << string_view( "123" ); + + BOOST_TEST_EQ( os.str(), std::string( "123 " ) ); + } + + { + std::ostringstream os; + + os << std::right << std::setw( 5 ) << string_view( "123" ); + + BOOST_TEST_EQ( os.str(), std::string( " 123" ) ); + } + + { + std::ostringstream os; + + os << std::setfill( '-' ) << std::setw( 5 ) << string_view( "123" ); + + BOOST_TEST_EQ( os.str(), std::string( "--123" ) ); + } + + { + std::ostringstream os; + + os << std::setfill( '-' ) << std::left << std::setw( 5 ) << string_view( "123" ); + + BOOST_TEST_EQ( os.str(), std::string( "123--" ) ); + } + + { + std::ostringstream os; + + os << std::setfill( '-' ) << std::right << std::setw( 5 ) << string_view( "123" ); + + BOOST_TEST_EQ( os.str(), std::string( "--123" ) ); + } + + { + std::ostringstream os; + + os << std::setw( 5 ) << string_view( "12345" ); + + BOOST_TEST_EQ( os.str(), std::string( "12345" ) ); + } + + { + std::ostringstream os; + + os << std::setw( 5 ) << string_view( "1234567" ); + + BOOST_TEST_EQ( os.str(), std::string( "1234567" ) ); + } + + return boost::report_errors(); +} From d17313d4077cc467cabddb394ecedcc6abe08f5a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 18:00:58 +0300 Subject: [PATCH 067/258] Add missing #include --- include/boost/core/string_view.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index d9704bd..941891a 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -27,6 +27,7 @@ #include #include #include +#include #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) # include #endif From ddf9b5087bb6e98ec5ef6bd8402379edf7350ba2 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 18:36:05 +0300 Subject: [PATCH 068/258] Add sv_conversion_test --- include/boost/core/string_view.hpp | 221 +++++++++++++++++++++++++++++ test/Jamfile.v2 | 1 + test/sv_conversion_test.cpp | 38 +++++ 3 files changed, 260 insertions(+) create mode 100644 test/sv_conversion_test.cpp diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index 941891a..4cb120c 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -381,6 +381,35 @@ public: // BOOST_CONSTEXPR basic_string_view& operator=( basic_string_view const& ) BOOST_NOEXCEPT & = default; + // conversions + +#if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) + + template >::type> + operator std::basic_string() const + { + return std::basic_string( data(), size() ); + } + +#else + + operator std::basic_string() const + { + return std::basic_string( data(), size() ); + } + +#endif + +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) + + template >::type> + operator std::basic_string_view() const BOOST_NOEXCEPT + { + return std::basic_string_view( data(), size() ); + } + +#endif + // iterator support BOOST_CONSTEXPR const_iterator begin() const BOOST_NOEXCEPT @@ -925,6 +954,198 @@ public: { return sv1.compare( sv2 ) >= 0; } + +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) + + // "sufficient number of additional overloads" + + // against std::string_view + + BOOST_CXX14_CONSTEXPR friend bool operator==( basic_string_view sv1, std::basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) == 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator==( std::basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) == 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator!=( basic_string_view sv1, std::basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) != 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator!=( std::basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) != 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator<( basic_string_view sv1, std::basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) < 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator<( std::basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) < 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator<=( basic_string_view sv1, std::basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) <= 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator<=( std::basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) <= 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator>( basic_string_view sv1, std::basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) > 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator>( std::basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) > 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator>=( basic_string_view sv1, std::basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) >= 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator>=( std::basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) >= 0; + } + + // against Ch const* + + BOOST_CXX14_CONSTEXPR friend bool operator==( basic_string_view sv1, Ch const* sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) == 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator==( Ch const* sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv2.compare( sv1 ) == 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator!=( basic_string_view sv1, Ch const* sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) != 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator!=( Ch const* sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv2.compare( sv1 ) != 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator<( basic_string_view sv1, Ch const* sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) < 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator<( Ch const* sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv2.compare( sv1 ) > 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator<=( basic_string_view sv1, Ch const* sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) <= 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator<=( Ch const* sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv2.compare( sv1 ) >= 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator>( basic_string_view sv1, Ch const* sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) > 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator>( Ch const* sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv2.compare( sv1 ) < 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator>=( basic_string_view sv1, Ch const* sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) >= 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator>=( Ch const* sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv2.compare( sv1 ) <= 0; + } + + // against std::string + + BOOST_CXX14_CONSTEXPR friend bool operator==( basic_string_view sv1, std::basic_string const& sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) == 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator==( std::basic_string const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv2.compare( sv1 ) == 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator!=( basic_string_view sv1, std::basic_string const& sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) != 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator!=( std::basic_string const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv2.compare( sv1 ) != 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator<( basic_string_view sv1, std::basic_string const& sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) < 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator<( std::basic_string const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv2.compare( sv1 ) > 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator<=( basic_string_view sv1, std::basic_string const& sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) <= 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator<=( std::basic_string const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv2.compare( sv1 ) >= 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator>( basic_string_view sv1, std::basic_string const& sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) > 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator>( std::basic_string const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv2.compare( sv1 ) < 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator>=( basic_string_view sv1, std::basic_string const& sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) >= 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator>=( std::basic_string const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv2.compare( sv1 ) <= 0; + } + +#endif }; template std::basic_ostream& operator<<( std::basic_ostream& os, basic_string_view str ) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index b6c89b5..7a1912c 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -267,6 +267,7 @@ run sv_contains_test.cpp ; run sv_eq_test.cpp ; run sv_lt_test.cpp ; run sv_stream_insert_test.cpp ; +run sv_conversion_test.cpp ; use-project /boost/core/swap : ./swap ; build-project ./swap ; diff --git a/test/sv_conversion_test.cpp b/test/sv_conversion_test.cpp new file mode 100644 index 0000000..fb77e8d --- /dev/null +++ b/test/sv_conversion_test.cpp @@ -0,0 +1,38 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) +# include +#endif + +boost::core::string_view f( boost::core::string_view const& str ) +{ + return str; +} + +int main() +{ + { + std::string s1( "123" ); + std::string s2 = f( s1 ); + + BOOST_TEST_EQ( s1, s2 ); + } + +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) + + { + std::string_view s1( "123" ); + std::string_view s2 = f( s1 ); + + BOOST_TEST_EQ( s1, s2 ); + } + +#endif + + return boost::report_errors(); +} From c43a172ded94c6b8bd067a9f60c59d1b772fbf86 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 19:31:41 +0300 Subject: [PATCH 069/258] Use `os << ""` for the padding instead of `os << p[0]` --- include/boost/core/string_view.hpp | 33 ++++++++++++------------------ 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index 4cb120c..2aae97b 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -1153,32 +1153,25 @@ template std::basic_ostream& operator<<( std::basic_ostream& o Ch const* p = str.data(); std::size_t n = str.size(); - if( n == 0 ) + std::size_t m = os.width(); + + if( n >= m ) { + os.write( p, n ); + } + else if( ( os.flags() & std::ios_base::adjustfield ) == std::ios_base::left ) + { + os.write( p, n ); + + os.width( m - n ); os << ""; } else { - std::size_t m = os.width(); + os.width( m - n ); + os << ""; - if( n >= m ) - { - os.write( p, n ); - } - else if( ( os.flags() & std::ios_base::adjustfield ) == std::ios_base::left ) - { - os.write( p, n - 1 ); - - os.width( m - n + 1 ); - os << p[ n-1 ]; - } - else - { - os.width( m - n + 1 ); - os << p[0]; - - os.write( p + 1, n - 1 ); - } + os.write( p, n ); } os.width( 0 ); From 54965f567dc899a4ee2b8eb8be8b8b5563a65315 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 19:50:15 +0300 Subject: [PATCH 070/258] Add an allocator argument to operator string() --- include/boost/core/string_view.hpp | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index 2aae97b..4272b69 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -383,23 +383,11 @@ public: // conversions -#if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) - - template >::type> - operator std::basic_string() const + template operator std::basic_string, A>() const { - return std::basic_string( data(), size() ); + return std::basic_string, A>( data(), size() ); } -#else - - operator std::basic_string() const - { - return std::basic_string( data(), size() ); - } - -#endif - #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) template >::type> From 88eee0c628c6fab689ddadf2dd5e76b566e3cbcf Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 19:50:34 +0300 Subject: [PATCH 071/258] Test std::pmr::string in sv_construct_test --- test/sv_construct_test.cpp | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/test/sv_construct_test.cpp b/test/sv_construct_test.cpp index 3e7343d..5107d97 100644 --- a/test/sv_construct_test.cpp +++ b/test/sv_construct_test.cpp @@ -299,6 +299,42 @@ int main() } } +#endif + +#if !defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE) + + { + std::pmr::string str = "123"; + + boost::core::string_view sv( str ); + + BOOST_TEST_EQ( sv.data(), str.data() ); + BOOST_TEST_EQ( sv.size(), str.size() ); + + BOOST_TEST_EQ( sv.begin(), sv.data() ); + BOOST_TEST_EQ( sv.end(), sv.data() + sv.size() ); + + BOOST_TEST_EQ( sv.cbegin(), sv.data() ); + BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); + + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.begin() ) ); + + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cbegin() ) ); + + BOOST_TEST_EQ( sv.length(), sv.size() ); + BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); + + BOOST_TEST_EQ( sv.max_size(), boost::core::string_view::npos ); + + if( !sv.empty() ) + { + BOOST_TEST_EQ( &sv.front(), sv.data() ); + BOOST_TEST_EQ( &sv.back(), sv.data() + sv.size() - 1 ); + } + } + #endif return boost::report_errors(); From 903d44c0c569dba4d764c4ac9d12a3f25aad4576 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 19:52:10 +0300 Subject: [PATCH 072/258] Test std::pmr::string in sv_conversion_test --- test/sv_conversion_test.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/sv_conversion_test.cpp b/test/sv_conversion_test.cpp index fb77e8d..5208d49 100644 --- a/test/sv_conversion_test.cpp +++ b/test/sv_conversion_test.cpp @@ -32,6 +32,17 @@ int main() BOOST_TEST_EQ( s1, s2 ); } +#endif + +#if !defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE) + + { + std::pmr::string s1( "123" ); + std::pmr::string s2 = f( s1 ); + + BOOST_TEST_EQ( s1, s2 ); + } + #endif return boost::report_errors(); From 9b22937647110bfc97a1606b178df17cc13a1eaf Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 20:06:20 +0300 Subject: [PATCH 073/258] g++ 11 has but not std::pmr::string --- test/sv_construct_test.cpp | 7 ++++++- test/sv_conversion_test.cpp | 9 +++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/test/sv_construct_test.cpp b/test/sv_construct_test.cpp index 5107d97..0147828 100644 --- a/test/sv_construct_test.cpp +++ b/test/sv_construct_test.cpp @@ -9,6 +9,9 @@ #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) # include #endif +#if !defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE) +# include +#endif template std::reverse_iterator make_reverse_iterator( It it ) { @@ -304,7 +307,9 @@ int main() #if !defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE) { - std::pmr::string str = "123"; + using pmr_string = std::basic_string, std::pmr::polymorphic_allocator>; + + pmr_string str = "123"; boost::core::string_view sv( str ); diff --git a/test/sv_conversion_test.cpp b/test/sv_conversion_test.cpp index 5208d49..604b1f9 100644 --- a/test/sv_conversion_test.cpp +++ b/test/sv_conversion_test.cpp @@ -8,6 +8,9 @@ #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) # include #endif +#if !defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE) +# include +#endif boost::core::string_view f( boost::core::string_view const& str ) { @@ -37,8 +40,10 @@ int main() #if !defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE) { - std::pmr::string s1( "123" ); - std::pmr::string s2 = f( s1 ); + using pmr_string = std::basic_string, std::pmr::polymorphic_allocator>; + + pmr_string s1( "123" ); + pmr_string s2 = f( s1 ); BOOST_TEST_EQ( s1, s2 ); } From b520289660c5f81ff31510ba01d68256ddffcecf Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 20:12:32 +0300 Subject: [PATCH 074/258] Test std::pmr::string in sv_eq_test --- include/boost/core/string_view.hpp | 24 ++++++++++++------------ test/sv_eq_test.cpp | 21 +++++++++++++++++++++ 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index 4272b69..246e79c 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -1073,62 +1073,62 @@ public: // against std::string - BOOST_CXX14_CONSTEXPR friend bool operator==( basic_string_view sv1, std::basic_string const& sv2 ) BOOST_NOEXCEPT + template BOOST_CXX14_CONSTEXPR friend bool operator==( basic_string_view sv1, std::basic_string, A> const& sv2 ) BOOST_NOEXCEPT { return sv1.compare( sv2 ) == 0; } - BOOST_CXX14_CONSTEXPR friend bool operator==( std::basic_string const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + template BOOST_CXX14_CONSTEXPR friend bool operator==( std::basic_string, A> const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT { return sv2.compare( sv1 ) == 0; } - BOOST_CXX14_CONSTEXPR friend bool operator!=( basic_string_view sv1, std::basic_string const& sv2 ) BOOST_NOEXCEPT + template BOOST_CXX14_CONSTEXPR friend bool operator!=( basic_string_view sv1, std::basic_string, A> const& sv2 ) BOOST_NOEXCEPT { return sv1.compare( sv2 ) != 0; } - BOOST_CXX14_CONSTEXPR friend bool operator!=( std::basic_string const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + template BOOST_CXX14_CONSTEXPR friend bool operator!=( std::basic_string, A> const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT { return sv2.compare( sv1 ) != 0; } - BOOST_CXX14_CONSTEXPR friend bool operator<( basic_string_view sv1, std::basic_string const& sv2 ) BOOST_NOEXCEPT + template BOOST_CXX14_CONSTEXPR friend bool operator<( basic_string_view sv1, std::basic_string, A> const& sv2 ) BOOST_NOEXCEPT { return sv1.compare( sv2 ) < 0; } - BOOST_CXX14_CONSTEXPR friend bool operator<( std::basic_string const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + template BOOST_CXX14_CONSTEXPR friend bool operator<( std::basic_string, A> const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT { return sv2.compare( sv1 ) > 0; } - BOOST_CXX14_CONSTEXPR friend bool operator<=( basic_string_view sv1, std::basic_string const& sv2 ) BOOST_NOEXCEPT + template BOOST_CXX14_CONSTEXPR friend bool operator<=( basic_string_view sv1, std::basic_string, A> const& sv2 ) BOOST_NOEXCEPT { return sv1.compare( sv2 ) <= 0; } - BOOST_CXX14_CONSTEXPR friend bool operator<=( std::basic_string const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + template BOOST_CXX14_CONSTEXPR friend bool operator<=( std::basic_string, A> const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT { return sv2.compare( sv1 ) >= 0; } - BOOST_CXX14_CONSTEXPR friend bool operator>( basic_string_view sv1, std::basic_string const& sv2 ) BOOST_NOEXCEPT + template BOOST_CXX14_CONSTEXPR friend bool operator>( basic_string_view sv1, std::basic_string, A> const& sv2 ) BOOST_NOEXCEPT { return sv1.compare( sv2 ) > 0; } - BOOST_CXX14_CONSTEXPR friend bool operator>( std::basic_string const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + template BOOST_CXX14_CONSTEXPR friend bool operator>( std::basic_string, A> const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT { return sv2.compare( sv1 ) < 0; } - BOOST_CXX14_CONSTEXPR friend bool operator>=( basic_string_view sv1, std::basic_string const& sv2 ) BOOST_NOEXCEPT + template BOOST_CXX14_CONSTEXPR friend bool operator>=( basic_string_view sv1, std::basic_string, A> const& sv2 ) BOOST_NOEXCEPT { return sv1.compare( sv2 ) >= 0; } - BOOST_CXX14_CONSTEXPR friend bool operator>=( std::basic_string const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + template BOOST_CXX14_CONSTEXPR friend bool operator>=( std::basic_string, A> const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT { return sv2.compare( sv1 ) <= 0; } diff --git a/test/sv_eq_test.cpp b/test/sv_eq_test.cpp index 3511a14..ea48831 100644 --- a/test/sv_eq_test.cpp +++ b/test/sv_eq_test.cpp @@ -8,6 +8,9 @@ #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) # include #endif +#if !defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE) +# include +#endif #define TEST_EQ(x, y) \ BOOST_TEST_EQ(x, y); \ @@ -85,6 +88,24 @@ int main() BOOST_TEST_NE( sv3, std::string_view( "122" ) ); BOOST_TEST_NE( std::string_view( "122" ), sv3 ); +#endif + +#if !defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE) + + using pmr_string = std::basic_string, std::pmr::polymorphic_allocator>; + + BOOST_TEST_EQ( sv1, pmr_string( "" ) ); + BOOST_TEST_EQ( pmr_string( "" ), sv1 ); + + BOOST_TEST_NE( sv1, pmr_string( "1" ) ); + BOOST_TEST_NE( pmr_string( "1" ), sv1 ); + + BOOST_TEST_EQ( sv3, pmr_string( "123" ) ); + BOOST_TEST_EQ( pmr_string( "123" ), sv3 ); + + BOOST_TEST_NE( sv3, pmr_string( "122" ) ); + BOOST_TEST_NE( pmr_string( "122" ), sv3 ); + #endif } From 15fdc0ab39dd13cfd184349f2a5d5dda67835da5 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 20:14:06 +0300 Subject: [PATCH 075/258] Test std::pmr::string in sv_lt_test --- test/sv_lt_test.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/sv_lt_test.cpp b/test/sv_lt_test.cpp index 0c78b91..8c45150 100644 --- a/test/sv_lt_test.cpp +++ b/test/sv_lt_test.cpp @@ -8,6 +8,9 @@ #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) # include #endif +#if !defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE) +# include +#endif #define TEST_LT(x, y) \ BOOST_TEST_LT(x, y); \ @@ -86,6 +89,19 @@ int main() TEST_LT( std::string_view( "123" ), sv5 ); TEST_LT( std::string_view( "1234" ), sv4 ); +#endif + +#if !defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE) + + using pmr_string = std::basic_string, std::pmr::polymorphic_allocator>; + + TEST_LT( pmr_string( "" ), sv1 ); + TEST_LT( pmr_string( "12" ), sv2 ); + TEST_LT( pmr_string( "122" ), sv3 ); + TEST_LT( pmr_string( "123" ), sv4 ); + TEST_LT( pmr_string( "123" ), sv5 ); + TEST_LT( pmr_string( "1234" ), sv4 ); + #endif } From 52c58efc362b010c9936e83f2ca4c41ffe6427c1 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 9 Oct 2021 21:04:38 +0300 Subject: [PATCH 076/258] Improve operator== --- include/boost/core/string_view.hpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index 246e79c..d7fd3b2 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -915,12 +915,12 @@ public: BOOST_CXX14_CONSTEXPR friend bool operator==( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT { - return sv1.compare( sv2 ) == 0; + return sv1.size() == sv2.size() && traits_type::compare( sv1.data(), sv2.data(), sv1.size() ) == 0; } BOOST_CXX14_CONSTEXPR friend bool operator!=( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT { - return sv1.compare( sv2 ) != 0; + return !( sv1 == sv2 ); } BOOST_CXX14_CONSTEXPR friend bool operator<( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT @@ -951,22 +951,22 @@ public: BOOST_CXX14_CONSTEXPR friend bool operator==( basic_string_view sv1, std::basic_string_view sv2 ) BOOST_NOEXCEPT { - return sv1.compare( sv2 ) == 0; + return sv1.size() == sv2.size() && traits_type::compare( sv1.data(), sv2.data(), sv1.size() ) == 0; } BOOST_CXX14_CONSTEXPR friend bool operator==( std::basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT { - return sv1.compare( sv2 ) == 0; + return sv1.size() == sv2.size() && traits_type::compare( sv1.data(), sv2.data(), sv1.size() ) == 0; } BOOST_CXX14_CONSTEXPR friend bool operator!=( basic_string_view sv1, std::basic_string_view sv2 ) BOOST_NOEXCEPT { - return sv1.compare( sv2 ) != 0; + return !( sv1 == sv2 ); } BOOST_CXX14_CONSTEXPR friend bool operator!=( std::basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT { - return sv1.compare( sv2 ) != 0; + return !( sv1 == sv2 ); } BOOST_CXX14_CONSTEXPR friend bool operator<( basic_string_view sv1, std::basic_string_view sv2 ) BOOST_NOEXCEPT @@ -1013,22 +1013,22 @@ public: BOOST_CXX14_CONSTEXPR friend bool operator==( basic_string_view sv1, Ch const* sv2 ) BOOST_NOEXCEPT { - return sv1.compare( sv2 ) == 0; + return sv1 == basic_string_view( sv2 ); } BOOST_CXX14_CONSTEXPR friend bool operator==( Ch const* sv1, basic_string_view sv2 ) BOOST_NOEXCEPT { - return sv2.compare( sv1 ) == 0; + return basic_string_view( sv1 ) == sv2; } BOOST_CXX14_CONSTEXPR friend bool operator!=( basic_string_view sv1, Ch const* sv2 ) BOOST_NOEXCEPT { - return sv1.compare( sv2 ) != 0; + return !( sv1 == sv2 ); } BOOST_CXX14_CONSTEXPR friend bool operator!=( Ch const* sv1, basic_string_view sv2 ) BOOST_NOEXCEPT { - return sv2.compare( sv1 ) != 0; + return !( sv1 == sv2 ); } BOOST_CXX14_CONSTEXPR friend bool operator<( basic_string_view sv1, Ch const* sv2 ) BOOST_NOEXCEPT @@ -1075,22 +1075,22 @@ public: template BOOST_CXX14_CONSTEXPR friend bool operator==( basic_string_view sv1, std::basic_string, A> const& sv2 ) BOOST_NOEXCEPT { - return sv1.compare( sv2 ) == 0; + return sv1.size() == sv2.size() && traits_type::compare( sv1.data(), sv2.data(), sv1.size() ) == 0; } template BOOST_CXX14_CONSTEXPR friend bool operator==( std::basic_string, A> const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT { - return sv2.compare( sv1 ) == 0; + return sv1.size() == sv2.size() && traits_type::compare( sv1.data(), sv2.data(), sv1.size() ) == 0; } template BOOST_CXX14_CONSTEXPR friend bool operator!=( basic_string_view sv1, std::basic_string, A> const& sv2 ) BOOST_NOEXCEPT { - return sv1.compare( sv2 ) != 0; + return !( sv1 == sv2 ); } template BOOST_CXX14_CONSTEXPR friend bool operator!=( std::basic_string, A> const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT { - return sv2.compare( sv1 ) != 0; + return !( sv1 == sv2 ); } template BOOST_CXX14_CONSTEXPR friend bool operator<( basic_string_view sv1, std::basic_string, A> const& sv2 ) BOOST_NOEXCEPT From 038064e8241fa1fe97ebfd4cbd8f03736f35304d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 10 Oct 2021 00:44:00 +0300 Subject: [PATCH 077/258] Update string_view.qbk --- doc/string_view.qbk | 128 ++++++++++++++++++++++++++++- include/boost/core/string_view.hpp | 4 + 2 files changed, 129 insertions(+), 3 deletions(-) diff --git a/doc/string_view.qbk b/doc/string_view.qbk index 128c906..51c1e0b 100644 --- a/doc/string_view.qbk +++ b/doc/string_view.qbk @@ -68,8 +68,13 @@ public: constexpr basic_string_view( Ch const* str ) noexcept; constexpr basic_string_view( Ch const* str, size_type len ) noexcept; constexpr basic_string_view( Ch const* begin, Ch const* end ) noexcept; - template basic_string_view(std::basic_string, A> const& str ) noexcept; - basic_string_view(std::basic_string_view> const& str ) noexcept; + template basic_string_view( std::basic_string, A> const& str ) noexcept; + basic_string_view( std::basic_string_view> const& str ) noexcept; + + // conversions + + template operator std::basic_string, A>() const; + template operator std::basic_string_view() const noexcept; // iterator support @@ -108,6 +113,8 @@ public: constexpr size_type copy( Ch* s, size_type n, size_type pos = 0 ) const; constexpr basic_string_view substr( size_type pos = 0, size_type n = npos ) const; + // compare + constexpr int compare( basic_string_view s ) const noexcept; constexpr int compare( size_type pos1, size_type n1, basic_string_view s ) const; constexpr int compare( size_type pos1, size_type n1, basic_string_view s, size_type pos2, size_type n2 ) const; @@ -115,47 +122,82 @@ public: constexpr int compare( size_type pos1, size_type n1, Ch const* s ) const; constexpr int compare( size_type pos1, size_type n1, Ch const* s, size_type n2 ) const; + // starts_with + constexpr bool starts_with( basic_string_view x ) const noexcept; constexpr bool starts_with( Ch x ) const noexcept; constexpr bool starts_with( Ch const* x ) const; + // ends_with + constexpr bool ends_with( basic_string_view x ) const noexcept; constexpr bool ends_with( Ch x ) const noexcept; constexpr bool ends_with( Ch const* x ) const; - // searching + // find constexpr size_type find( basic_string_view s, size_type pos = 0 ) const noexcept; constexpr size_type find( Ch c, size_type pos = 0 ) const noexcept; constexpr size_type find( Ch const* s, size_type pos, size_type n ) const; constexpr size_type find( Ch const* s, size_type pos = 0 ) const; + // rfind + constexpr size_type rfind( basic_string_view s, size_type pos = npos ) const noexcept; constexpr size_type rfind( Ch c, size_type pos = npos ) const noexcept; constexpr size_type rfind( Ch const* s, size_type pos, size_type n ) const; constexpr size_type rfind( Ch const* s, size_type pos = npos ) const; + // find_first_of + constexpr size_type find_first_of( basic_string_view s, size_type pos = 0 ) const noexcept; constexpr size_type find_first_of( Ch c, size_type pos = 0 ) const noexcept; constexpr size_type find_first_of( Ch const* s, size_type pos, size_type n ) const; constexpr size_type find_first_of( Ch const* s, size_type pos = 0 ) const; + // find_last_of + constexpr size_type find_last_of( basic_string_view s, size_type pos = npos ) const noexcept; constexpr size_type find_last_of( Ch c, size_type pos = npos ) const noexcept; constexpr size_type find_last_of( Ch const* s, size_type pos, size_type n ) const; constexpr size_type find_last_of( Ch const* s, size_type pos = npos ) const; + // find_first_not_of + constexpr size_type find_first_not_of( basic_string_view s, size_type pos = 0 ) const noexcept; constexpr size_type find_first_not_of( Ch c, size_type pos = 0 ) const noexcept; constexpr size_type find_first_not_of( Ch const* s, size_type pos, size_type n ) const; constexpr size_type find_first_not_of( Ch const* s, size_type pos = 0 ) const; + // find_last_not_of + constexpr size_type find_last_not_of( basic_string_view s, size_type pos = npos ) const noexcept; constexpr size_type find_last_not_of( Ch c, size_type pos = npos ) const noexcept; constexpr size_type find_last_not_of( Ch const* s, size_type pos, size_type n ) const; constexpr size_type find_last_not_of( Ch const* s, size_type pos = npos ) const; + + // contains + + constexpr bool contains( basic_string_view sv ) const noexcept; + constexpr bool contains( Ch c ) const noexcept; + constexpr bool contains( Ch const* s ) const noexcept; + + // relational operators + + constexpr friend bool operator==( basic_string_view sv1, basic_string_view sv2 ) noexcept; + constexpr friend bool operator!=( basic_string_view sv1, basic_string_view sv2 ) noexcept; + constexpr friend bool operator<( basic_string_view sv1, basic_string_view sv2 ) noexcept; + constexpr friend bool operator<=( basic_string_view sv1, basic_string_view sv2 ) noexcept; + constexpr friend bool operator>( basic_string_view sv1, basic_string_view sv2 ) noexcept; + constexpr friend bool operator>=( basic_string_view sv1, basic_string_view sv2 ) noexcept; }; +// stream inserter + +template std::basic_ostream& operator<<( std::basic_ostream& os, basic_string_view str ) + +// typedef names + typedef basic_string_view string_view; typedef basic_string_view wstring_view; typedef basic_string_view u16string_view; @@ -176,6 +218,86 @@ typedef basic_string_view u8string_view; [endsect] +[section constexpr basic_string_view( Ch const* str ) noexcept;] +[endsect] + +[section constexpr basic_string_view( Ch const* str, size_type len ) noexcept;] +[endsect] + +[section constexpr basic_string_view( Ch const* begin, Ch const* end ) noexcept;] +[endsect] + +[section template basic_string_view( std::basic_string, A> const& str ) noexcept;] +[endsect] + +[section basic_string_view( std::basic_string_view> const& str ) noexcept;] +[endsect] + +[endsect] + +[section Conversions] +[endsect] + +[section Iterator Support] +[endsect] + +[section Capacity] +[endsect] + +[section Element Access] +[endsect] + +[section Modifiers] +[endsect] + +[section String Operations] + +[section copy] +[endsect] + +[section substr] +[endsect] + +[section compare] +[endsect] + +[section starts_with] +[endsect] + +[section ends_with] +[endsect] + +[endsect] + +[section Searching] + +[section find] +[endsect] + +[section rfind] +[endsect] + +[section find_first_of] +[endsect] + +[section find_last_of] +[endsect] + +[section find_first_not_of] +[endsect] + +[section find_last_not_of] +[endsect] + +[section contains] +[endsect] + +[endsect] + +[section Relational Operators] +[endsect] + +[section Stream Inserter] [endsect] [endsect] diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index d7fd3b2..d74a6f2 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -1136,6 +1136,8 @@ public: #endif }; +// stream inserter + template std::basic_ostream& operator<<( std::basic_ostream& os, basic_string_view str ) { Ch const* p = str.data(); @@ -1170,6 +1172,8 @@ template std::basic_ostream& operator<<( std::basic_ostream& o template BOOST_CONSTEXPR_OR_CONST std::size_t basic_string_view::npos; #endif +// typedef names + typedef basic_string_view string_view; typedef basic_string_view wstring_view; From 7340f123fe58204fed592a90a0e733c633637ab7 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 10 Oct 2021 01:46:32 +0300 Subject: [PATCH 078/258] Update string_view.qbk --- doc/core.qbk | 3 +- doc/string_view.qbk | 489 +++++++++++++++++++++++++++-- include/boost/core/string_view.hpp | 4 +- 3 files changed, 467 insertions(+), 29 deletions(-) diff --git a/doc/core.qbk b/doc/core.qbk index 17538fe..9e2c1a5 100644 --- a/doc/core.qbk +++ b/doc/core.qbk @@ -34,7 +34,7 @@ criteria for inclusion is that the utility component be: * simple, * used by other Boost libraries, and * not dependent on any other Boost modules except Core - itself, Config, Assert, Static Assert, or Predef. + itself, Config, Assert, or Static Assert. [endsect] @@ -65,6 +65,7 @@ criteria for inclusion is that the utility component be: [include quick_exit.qbk] [include ref.qbk] [include scoped_enum.qbk] +[include string_view.qbk] [include swap.qbk] [include typeinfo.qbk] [include type_name.qbk] diff --git a/doc/string_view.qbk b/doc/string_view.qbk index 51c1e0b..f292e36 100644 --- a/doc/string_view.qbk +++ b/doc/string_view.qbk @@ -32,11 +32,6 @@ namespace core template class basic_string_view { -private: - - Ch const* data_; - std::size_t size_; - public: // types @@ -126,55 +121,55 @@ public: constexpr bool starts_with( basic_string_view x ) const noexcept; constexpr bool starts_with( Ch x ) const noexcept; - constexpr bool starts_with( Ch const* x ) const; + constexpr bool starts_with( Ch const* x ) const noexcept; // ends_with constexpr bool ends_with( basic_string_view x ) const noexcept; constexpr bool ends_with( Ch x ) const noexcept; - constexpr bool ends_with( Ch const* x ) const; + constexpr bool ends_with( Ch const* x ) const noexcept; // find constexpr size_type find( basic_string_view s, size_type pos = 0 ) const noexcept; constexpr size_type find( Ch c, size_type pos = 0 ) const noexcept; constexpr size_type find( Ch const* s, size_type pos, size_type n ) const; - constexpr size_type find( Ch const* s, size_type pos = 0 ) const; + constexpr size_type find( Ch const* s, size_type pos = 0 ) const noexcept; // rfind constexpr size_type rfind( basic_string_view s, size_type pos = npos ) const noexcept; constexpr size_type rfind( Ch c, size_type pos = npos ) const noexcept; - constexpr size_type rfind( Ch const* s, size_type pos, size_type n ) const; - constexpr size_type rfind( Ch const* s, size_type pos = npos ) const; + constexpr size_type rfind( Ch const* s, size_type pos, size_type n ) const noexcept; + constexpr size_type rfind( Ch const* s, size_type pos = npos ) const noexcept; // find_first_of constexpr size_type find_first_of( basic_string_view s, size_type pos = 0 ) const noexcept; constexpr size_type find_first_of( Ch c, size_type pos = 0 ) const noexcept; - constexpr size_type find_first_of( Ch const* s, size_type pos, size_type n ) const; - constexpr size_type find_first_of( Ch const* s, size_type pos = 0 ) const; + constexpr size_type find_first_of( Ch const* s, size_type pos, size_type n ) const noexcept; + constexpr size_type find_first_of( Ch const* s, size_type pos = 0 ) const noexcept; // find_last_of constexpr size_type find_last_of( basic_string_view s, size_type pos = npos ) const noexcept; constexpr size_type find_last_of( Ch c, size_type pos = npos ) const noexcept; - constexpr size_type find_last_of( Ch const* s, size_type pos, size_type n ) const; - constexpr size_type find_last_of( Ch const* s, size_type pos = npos ) const; + constexpr size_type find_last_of( Ch const* s, size_type pos, size_type n ) const noexcept; + constexpr size_type find_last_of( Ch const* s, size_type pos = npos ) const noexcept; // find_first_not_of constexpr size_type find_first_not_of( basic_string_view s, size_type pos = 0 ) const noexcept; constexpr size_type find_first_not_of( Ch c, size_type pos = 0 ) const noexcept; - constexpr size_type find_first_not_of( Ch const* s, size_type pos, size_type n ) const; - constexpr size_type find_first_not_of( Ch const* s, size_type pos = 0 ) const; + constexpr size_type find_first_not_of( Ch const* s, size_type pos, size_type n ) const noexcept; + constexpr size_type find_first_not_of( Ch const* s, size_type pos = 0 ) const noexcept; // find_last_not_of constexpr size_type find_last_not_of( basic_string_view s, size_type pos = npos ) const noexcept; constexpr size_type find_last_not_of( Ch c, size_type pos = npos ) const noexcept; - constexpr size_type find_last_not_of( Ch const* s, size_type pos, size_type n ) const; - constexpr size_type find_last_not_of( Ch const* s, size_type pos = npos ) const; + constexpr size_type find_last_not_of( Ch const* s, size_type pos, size_type n ) const noexcept; + constexpr size_type find_last_not_of( Ch const* s, size_type pos = npos ) const noexcept; // contains @@ -194,7 +189,7 @@ public: // stream inserter -template std::basic_ostream& operator<<( std::basic_ostream& os, basic_string_view str ) +template std::basic_ostream& operator<<( std::basic_ostream& os, basic_string_view str ); // typedef names @@ -212,59 +207,291 @@ typedef basic_string_view u8string_view; [section Construction] -[section constexpr basic_string_view() noexcept;] +[section `constexpr basic_string_view() noexcept;`] -* *Ensures:* `data() == 0`, `size() == 0`. +* *Ensures:* `data() == 0`; `size() == 0`. [endsect] -[section constexpr basic_string_view( Ch const* str ) noexcept;] +[section `constexpr basic_string_view( Ch const* str ) noexcept;`] + +* *Ensures:* `data() == str`; `size() == traits_type::length( str )`. + [endsect] -[section constexpr basic_string_view( Ch const* str, size_type len ) noexcept;] +[section `constexpr basic_string_view( Ch const* str, size_type len ) noexcept;`] + +* *Ensures:* `data() == str`; `size() == len`. + [endsect] -[section constexpr basic_string_view( Ch const* begin, Ch const* end ) noexcept;] +[section `constexpr basic_string_view( Ch const* begin, Ch const* end ) noexcept;`] + +* *Requires:* `end >= begin`. +* *Ensures:* `data() == begin`; `size() == end - begin`. + [endsect] -[section template basic_string_view( std::basic_string, A> const& str ) noexcept;] +[section `template basic_string_view( std::basic_string, A> const& str ) noexcept;`] + +* *Ensures:* `data() == str.data()`; `size() == str.size()`. + [endsect] -[section basic_string_view( std::basic_string_view> const& str ) noexcept;] +[section `basic_string_view( std::basic_string_view> const& str ) noexcept;`] + +* *Ensures:* `data() == str.data()`; `size() == str.size()`. + [endsect] [endsect] [section Conversions] + +[section `template operator std::basic_string, A>() const;`] + +* *Returns:* `std::basic_string, A>( data(), size() )`. + +[endsect] + +[section `template operator std::basic_string_view() const noexcept;`] + +* *Constraints:* `Ch2` is the same type as `Ch`. +* *Returns:* `std::basic_string_view( data(), size() )`. + +[endsect] + [endsect] [section Iterator Support] + +[section `constexpr const_iterator begin() const noexcept;`] + +* *Returns:* `data()`. + +[endsect] + +[section `constexpr const_iterator end() const noexcept;`] + +* *Returns:* `data() + size()`. + +[endsect] + +[section `constexpr const_iterator cbegin() const noexcept;`] + +* *Returns:* `begin()`. + +[endsect] + +[section `constexpr const_iterator cend() const noexcept;`] + +* *Returns:* `end()`. + +[endsect] + +[section `constexpr const_reverse_iterator rbegin() const noexcept;`] + +* *Returns:* `std::make_reverse_iterator( end() )`. + +[endsect] + +[section `constexpr const_reverse_iterator rend() const noexcept;`] + +* *Returns:* `std::make_reverse_iterator( begin() )`. + +[endsect] + +[section `constexpr const_reverse_iterator crbegin() const noexcept;`] + +* *Returns:* `rbegin()`. + +[endsect] + +[section `constexpr const_reverse_iterator crend() const noexcept;`] + +* *Returns:* `rend()`. + +[endsect] + [endsect] [section Capacity] + +[section `constexpr size_type size() const noexcept;`] + +* *Returns:* the length of the referenced character sequence. + +[endsect] + +[section `constexpr size_type length() const noexcept;`] + +* *Returns:* `size()`. + +[endsect] + +[section `constexpr size_type max_size() const noexcept;`] + +* *Returns:* `std::numeric_limits::max() / sizeof(Ch)`. + +[endsect] + +[section `constexpr bool empty() const noexcept;`] + +* *Returns:* `size() == 0`. + +[endsect] + [endsect] [section Element Access] + +[section `constexpr const_reference operator[]( size_type pos ) const noexcept;`] + +* *Requires:* `pos < size()`. +* *Returns:* `data()[ pos ]`. + +[endsect] + +[section `constexpr const_reference at( size_type pos ) const;`] + +* *Returns:* `data()[ pos ]`. +* *Throws:* `std::out_of_range` when `pos >= size()`. + +[endsect] + +[section `constexpr const_reference front() const noexcept;`] + +* *Requires:* `!empty()`. +* *Returns:* `data()[ 0 ]`. + +[endsect] + +[section `constexpr const_reference back() const noexcept;`] + +* *Requires:* `!empty()`. +* *Returns:* `data()[ size() - 1 ]`. + +[endsect] + +[section `constexpr const_pointer data() const noexcept;`] + +* *Returns:* a pointer to the beginning of the referenced character sequence. + +[endsect] + [endsect] [section Modifiers] + +[section `constexpr void remove_prefix( size_type n ) noexcept;`] +[endsect] + +[section `constexpr void remove_suffix( size_type n ) noexcept;`] +[endsect] + +[section `constexpr void swap( basic_string_view& s ) noexcept;`] +[endsect] + [endsect] [section String Operations] [section copy] + +[section `constexpr size_type copy( Ch* s, size_type n, size_type pos = 0 ) const;`] +[endsect] + [endsect] [section substr] + +[section `constexpr basic_string_view substr( size_type pos = 0, size_type n = npos ) const;`] +[endsect] + [endsect] [section compare] + +[section `constexpr int compare( basic_string_view s ) const noexcept;`] + +* *Returns:* `...`. + +[endsect] + +[section `constexpr int compare( size_type pos1, size_type n1, basic_string_view s ) const;`] + +* *Returns:* `substr( pos1, n1 ).compare( str )`. + +[endsect] + +[section `constexpr int compare( size_type pos1, size_type n1, basic_string_view s, size_type pos2, size_type n2 ) const;`] + +* *Returns:* `substr( pos1, n1 ).compare( str.substr( pos2, n2 ) )`. + +[endsect] + +[section `constexpr int compare( Ch const* s ) const noexcept;`] + +* *Returns:* `compare( basic_string_view( s ) )`. + +[endsect] + +[section `constexpr int compare( size_type pos1, size_type n1, Ch const* s ) const;`] + +* *Returns:* `substr( pos1, n1 ).compare( basic_string_view( s ) )`. + +[endsect] + +[section `constexpr int compare( size_type pos1, size_type n1, Ch const* s, size_type n2 ) const;`] + +* *Returns:* `substr( pos1, n1 ).compare( basic_string_view( s, n2 ) )`. + +[endsect] + [endsect] [section starts_with] + +[section `constexpr bool starts_with( basic_string_view x ) const noexcept;`] + +* *Returns:* `...`. + +[endsect] + +[section `constexpr bool starts_with( Ch x ) const noexcept;`] + +* *Returns:* `...`. + +[endsect] + +[section `constexpr bool starts_with( Ch const* x ) const noexcept;`] + +* *Returns:* `starts_with( basic_string_view( x ) )`. + +[endsect] + [endsect] [section ends_with] + +[section `constexpr bool ends_with( basic_string_view x ) const noexcept;`] + +* *Returns:* `...`. + +[endsect] + +[section `constexpr bool ends_with( Ch x ) const noexcept;`] + +* *Returns:* `...`. + +[endsect] + +[section `constexpr bool ends_with( Ch const* x ) const noexcept;`] + +* *Returns:* `ends_with( basic_string_view( x ) )`. + +[endsect] + [endsect] [endsect] @@ -272,32 +499,242 @@ typedef basic_string_view u8string_view; [section Searching] [section find] + +[section `constexpr size_type find( basic_string_view s, size_type pos = 0 ) const noexcept;`] + +* *Returns:* `...`. + +[endsect] + +[section `constexpr size_type find( Ch c, size_type pos = 0 ) const noexcept;`] + +* *Returns:* `find( basic_string_view( &c, 1 ), pos )`. + +[endsect] + +[section `constexpr size_type find( Ch const* s, size_type pos, size_type n ) const noexcept;`] + +* *Returns:* `find( basic_string_view( s, n ), pos )`. + +[endsect] + +[section `constexpr size_type find( Ch const* s, size_type pos = 0 ) const noexcept;`] + +* *Returns:* `find( basic_string_view( s ), pos )`. + +[endsect] + [endsect] [section rfind] + +[section `constexpr size_type rfind( basic_string_view s, size_type pos = npos ) const noexcept;`] + +* *Returns:* `...`. + +[endsect] + +[section `constexpr size_type rfind( Ch c, size_type pos = npos ) const noexcept;`] + +* *Returns:* `rfind( basic_string_view( &c, 1 ), pos )`. + +[endsect] + +[section `constexpr size_type rfind( Ch const* s, size_type pos, size_type n ) const noexcept;`] + +* *Returns:* `rfind( basic_string_view( s, n ), pos )`. + +[endsect] + +[section `constexpr size_type rfind( Ch const* s, size_type pos = npos ) const noexcept;`] + +* *Returns:* `rfind( basic_string_view( s ), pos )`. + +[endsect] + [endsect] [section find_first_of] + +[section `constexpr size_type find_first_of( basic_string_view s, size_type pos = 0 ) const noexcept;`] + +* *Returns:* `...`. + +[endsect] + +[section `constexpr size_type find_first_of( Ch c, size_type pos = 0 ) const noexcept;`] + +* *Returns:* `find_first_of( basic_string_view( &c, 1 ), pos )`. + +[endsect] + +[section `constexpr size_type find_first_of( Ch const* s, size_type pos, size_type n ) const noexcept;`] + +* *Returns:* `find_first_of( basic_string_view( s, n ), pos )`. + +[endsect] + +[section `constexpr size_type find_first_of( Ch const* s, size_type pos = 0 ) const noexcept;`] + +* *Returns:* `find_first_of( basic_string_view( s ), pos )`. + +[endsect] + [endsect] [section find_last_of] + +[section `constexpr size_type find_last_of( basic_string_view s, size_type pos = npos ) const noexcept;`] + +* *Returns:* `...`. + +[endsect] + +[section `constexpr size_type find_last_of( Ch c, size_type pos = npos ) const noexcept;`] + +* *Returns:* `find_last_of( basic_string_view( &c, 1 ), pos )`. + +[endsect] + +[section `constexpr size_type find_last_of( Ch const* s, size_type pos, size_type n ) const noexcept;`] + +* *Returns:* `find_last_of( basic_string_view( s, n ), pos )`. + +[endsect] + +[section `constexpr size_type find_last_of( Ch const* s, size_type pos = npos ) const noexcept;`] + +* *Returns:* `find_last_of( basic_string_view( s ), pos )`. + +[endsect] + [endsect] [section find_first_not_of] + +[section `constexpr size_type find_first_not_of( basic_string_view s, size_type pos = 0 ) const noexcept;`] + +* *Returns:* `...`. + +[endsect] + +[section `constexpr size_type find_first_not_of( Ch c, size_type pos = 0 ) const noexcept;`] + +* *Returns:* `find_first_not_of( basic_string_view( &c, 1 ), pos )`. + +[endsect] + +[section `constexpr size_type find_first_not_of( Ch const* s, size_type pos, size_type n ) const noexcept;`] + +* *Returns:* `find_first_not_of( basic_string_view( s, n ), pos )`. + +[endsect] + +[section `constexpr size_type find_first_not_of( Ch const* s, size_type pos = 0 ) const noexcept;`] + +* *Returns:* `find_first_not_of( basic_string_view( s ), pos )`. + +[endsect] + [endsect] [section find_last_not_of] + +[section `constexpr size_type find_last_not_of( basic_string_view s, size_type pos = npos ) const noexcept;`] + +* *Returns:* `...`. + +[endsect] + +[section `constexpr size_type find_last_not_of( Ch c, size_type pos = npos ) const noexcept;`] + +* *Returns:* `find_last_not_of( basic_string_view( &c, 1 ), pos )`. + +[endsect] + +[section `constexpr size_type find_last_not_of( Ch const* s, size_type pos, size_type n ) const noexcept;`] + +* *Returns:* `find_last_not_of( basic_string_view( s, n ), pos )`. + +[endsect] + +[section `constexpr size_type find_last_not_of( Ch const* s, size_type pos = npos ) const noexcept;`] + +* *Returns:* `find_last_not_of( basic_string_view( s ), pos )`. + +[endsect] + [endsect] [section contains] + +[section `constexpr bool contains( basic_string_view sv ) const noexcept;`] + +* *Returns:* `find( sv ) != npos`. + +[endsect] + +[section `constexpr bool contains( Ch c ) const noexcept;`] + +* *Returns:* `find( c ) != npos`. + +[endsect] + +[section `constexpr bool contains( Ch const* s ) const noexcept;`] + +* *Returns:* `find( s ) != npos`. + +[endsect] + [endsect] [endsect] [section Relational Operators] + +[section `constexpr friend bool operator==( basic_string_view sv1, basic_string_view sv2 ) noexcept;`] + +* *Returns:* `sv1.compare( sv2 ) == 0`. + +[endsect] + +[section `constexpr friend bool operator!=( basic_string_view sv1, basic_string_view sv2 ) noexcept;`] + +* *Returns:* `sv1.compare( sv2 ) != 0`. + +[endsect] + +[section `constexpr friend bool operator<( basic_string_view sv1, basic_string_view sv2 ) noexcept;`] + +* *Returns:* `sv1.compare( sv2 ) < 0`. + +[endsect] + +[section `constexpr friend bool operator<=( basic_string_view sv1, basic_string_view sv2 ) noexcept;`] + +* *Returns:* `sv1.compare( sv2 ) <= 0`. + +[endsect] + +[section `constexpr friend bool operator>( basic_string_view sv1, basic_string_view sv2 ) noexcept;`] + +* *Returns:* `sv1.compare( sv2 ) > 0`. + +[endsect] + +[section `constexpr friend bool operator>=( basic_string_view sv1, basic_string_view sv2 ) noexcept;`] + +* *Returns:* `sv1.compare( sv2 ) >= 0`. + +[endsect] + [endsect] [section Stream Inserter] + +[section `template std::basic_ostream& operator<<( std::basic_ostream& os, basic_string_view str );`] +[endsect] + [endsect] [endsect] diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index d74a6f2..30186e9 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -600,7 +600,7 @@ public: return !empty() && front() == x; } - BOOST_CONSTEXPR bool starts_with( Ch const* x ) const + BOOST_CONSTEXPR bool starts_with( Ch const* x ) const BOOST_NOEXCEPT { return starts_with( basic_string_view( x ) ); } @@ -617,7 +617,7 @@ public: return !empty() && back() == x; } - BOOST_CONSTEXPR bool ends_with( Ch const* x ) const + BOOST_CONSTEXPR bool ends_with( Ch const* x ) const BOOST_NOEXCEPT { return ends_with( basic_string_view( x ) ); } From a47fac1449a0a3ba4f47ab77215162921d4a3dd5 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 10 Oct 2021 02:04:43 +0300 Subject: [PATCH 079/258] Update string_view.qbk --- doc/string_view.qbk | 73 +++++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 29 deletions(-) diff --git a/doc/string_view.qbk b/doc/string_view.qbk index f292e36..5d8c8f7 100644 --- a/doc/string_view.qbk +++ b/doc/string_view.qbk @@ -110,9 +110,9 @@ public: // compare - constexpr int compare( basic_string_view s ) const noexcept; - constexpr int compare( size_type pos1, size_type n1, basic_string_view s ) const; - constexpr int compare( size_type pos1, size_type n1, basic_string_view s, size_type pos2, size_type n2 ) const; + constexpr int compare( basic_string_view str ) const noexcept; + constexpr int compare( size_type pos1, size_type n1, basic_string_view str ) const; + constexpr int compare( size_type pos1, size_type n1, basic_string_view str, size_type pos2, size_type n2 ) const; constexpr int compare( Ch const* s ) const; constexpr int compare( size_type pos1, size_type n1, Ch const* s ) const; constexpr int compare( size_type pos1, size_type n1, Ch const* s, size_type n2 ) const; @@ -131,42 +131,42 @@ public: // find - constexpr size_type find( basic_string_view s, size_type pos = 0 ) const noexcept; + constexpr size_type find( basic_string_view str, size_type pos = 0 ) const noexcept; constexpr size_type find( Ch c, size_type pos = 0 ) const noexcept; constexpr size_type find( Ch const* s, size_type pos, size_type n ) const; constexpr size_type find( Ch const* s, size_type pos = 0 ) const noexcept; // rfind - constexpr size_type rfind( basic_string_view s, size_type pos = npos ) const noexcept; + constexpr size_type rfind( basic_string_view str, size_type pos = npos ) const noexcept; constexpr size_type rfind( Ch c, size_type pos = npos ) const noexcept; constexpr size_type rfind( Ch const* s, size_type pos, size_type n ) const noexcept; constexpr size_type rfind( Ch const* s, size_type pos = npos ) const noexcept; // find_first_of - constexpr size_type find_first_of( basic_string_view s, size_type pos = 0 ) const noexcept; + constexpr size_type find_first_of( basic_string_view str, size_type pos = 0 ) const noexcept; constexpr size_type find_first_of( Ch c, size_type pos = 0 ) const noexcept; constexpr size_type find_first_of( Ch const* s, size_type pos, size_type n ) const noexcept; constexpr size_type find_first_of( Ch const* s, size_type pos = 0 ) const noexcept; // find_last_of - constexpr size_type find_last_of( basic_string_view s, size_type pos = npos ) const noexcept; + constexpr size_type find_last_of( basic_string_view str, size_type pos = npos ) const noexcept; constexpr size_type find_last_of( Ch c, size_type pos = npos ) const noexcept; constexpr size_type find_last_of( Ch const* s, size_type pos, size_type n ) const noexcept; constexpr size_type find_last_of( Ch const* s, size_type pos = npos ) const noexcept; // find_first_not_of - constexpr size_type find_first_not_of( basic_string_view s, size_type pos = 0 ) const noexcept; + constexpr size_type find_first_not_of( basic_string_view str, size_type pos = 0 ) const noexcept; constexpr size_type find_first_not_of( Ch c, size_type pos = 0 ) const noexcept; constexpr size_type find_first_not_of( Ch const* s, size_type pos, size_type n ) const noexcept; constexpr size_type find_first_not_of( Ch const* s, size_type pos = 0 ) const noexcept; // find_last_not_of - constexpr size_type find_last_not_of( basic_string_view s, size_type pos = npos ) const noexcept; + constexpr size_type find_last_not_of( basic_string_view str, size_type pos = npos ) const noexcept; constexpr size_type find_last_not_of( Ch c, size_type pos = npos ) const noexcept; constexpr size_type find_last_not_of( Ch const* s, size_type pos, size_type n ) const noexcept; constexpr size_type find_last_not_of( Ch const* s, size_type pos = npos ) const noexcept; @@ -399,6 +399,10 @@ typedef basic_string_view u8string_view; [section copy] [section `constexpr size_type copy( Ch* s, size_type n, size_type pos = 0 ) const;`] + +* *Effects:* copies to `s` the contents of `substr( pos, n )`. +* *Throws:* `std::out_of_range` when `pos >= size()`. + [endsect] [endsect] @@ -406,25 +410,33 @@ typedef basic_string_view u8string_view; [section substr] [section `constexpr basic_string_view substr( size_type pos = 0, size_type n = npos ) const;`] + +* *Returns:* A `basic_string_view` object `r` such that `r.data() == data() + pos` and `r.size() == std::min( size() - pos, n )`. +* *Throws:* `std::out_of_range` when `pos >= size()`. + [endsect] [endsect] [section compare] -[section `constexpr int compare( basic_string_view s ) const noexcept;`] +[section `constexpr int compare( basic_string_view str ) const noexcept;`] -* *Returns:* `...`. +* *Returns:* + * if `traits_type::compare( data(), str.data(), std::min( size(), str.size() ) )` is not zero, returns it. Otherwise, + * if `size() < str.size()`, returns a negative number. Otherwise, + * if `size() > str.size()`, returns a positive number. Otherwise, + * returns 0. [endsect] -[section `constexpr int compare( size_type pos1, size_type n1, basic_string_view s ) const;`] +[section `constexpr int compare( size_type pos1, size_type n1, basic_string_view str ) const;`] * *Returns:* `substr( pos1, n1 ).compare( str )`. [endsect] -[section `constexpr int compare( size_type pos1, size_type n1, basic_string_view s, size_type pos2, size_type n2 ) const;`] +[section `constexpr int compare( size_type pos1, size_type n1, basic_string_view str, size_type pos2, size_type n2 ) const;`] * *Returns:* `substr( pos1, n1 ).compare( str.substr( pos2, n2 ) )`. @@ -454,13 +466,13 @@ typedef basic_string_view u8string_view; [section `constexpr bool starts_with( basic_string_view x ) const noexcept;`] -* *Returns:* `...`. +* *Returns:* `substr( 0, x.size() ) == x`. [endsect] [section `constexpr bool starts_with( Ch x ) const noexcept;`] -* *Returns:* `...`. +* *Returns:* `starts_with( basic_string_view( &x, 1 ) )`. [endsect] @@ -476,13 +488,13 @@ typedef basic_string_view u8string_view; [section `constexpr bool ends_with( basic_string_view x ) const noexcept;`] -* *Returns:* `...`. +* *Returns:* `size() >= x.size() && substr( size() - x.size(), x.size() ) == x`. [endsect] [section `constexpr bool ends_with( Ch x ) const noexcept;`] -* *Returns:* `...`. +* *Returns:* `ends_with( basic_string_view( &x, 1 ) )`. [endsect] @@ -500,9 +512,9 @@ typedef basic_string_view u8string_view; [section find] -[section `constexpr size_type find( basic_string_view s, size_type pos = 0 ) const noexcept;`] +[section `constexpr size_type find( basic_string_view str, size_type pos = 0 ) const noexcept;`] -* *Returns:* `...`. +* *Returns:* The lowest position `i` such that `i >= pos` and `substr( i, str.size() ) == str`, or `npos` if such a position doesn't exist. [endsect] @@ -528,9 +540,9 @@ typedef basic_string_view u8string_view; [section rfind] -[section `constexpr size_type rfind( basic_string_view s, size_type pos = npos ) const noexcept;`] +[section `constexpr size_type rfind( basic_string_view str, size_type pos = npos ) const noexcept;`] -* *Returns:* `...`. +* *Returns:* The highest position `i` such that `i <= pos` and `substr( i, str.size() ) == str`, or `npos` if such a position doesn't exist. [endsect] @@ -556,9 +568,9 @@ typedef basic_string_view u8string_view; [section find_first_of] -[section `constexpr size_type find_first_of( basic_string_view s, size_type pos = 0 ) const noexcept;`] +[section `constexpr size_type find_first_of( basic_string_view str, size_type pos = 0 ) const noexcept;`] -* *Returns:* `...`. +* *Returns:* The lowest position `i` such that `i >= pos` and the character at position `i` is equal to one of the characters in `str`, or `npos` if such a position doesn't exist. [endsect] @@ -584,9 +596,9 @@ typedef basic_string_view u8string_view; [section find_last_of] -[section `constexpr size_type find_last_of( basic_string_view s, size_type pos = npos ) const noexcept;`] +[section `constexpr size_type find_last_of( basic_string_view str, size_type pos = npos ) const noexcept;`] -* *Returns:* `...`. +* *Returns:* The highest position `i` such that `i <= pos` and the character at position `i` is equal to one of the characters in `str`, or `npos` if such a position doesn't exist. [endsect] @@ -612,9 +624,9 @@ typedef basic_string_view u8string_view; [section find_first_not_of] -[section `constexpr size_type find_first_not_of( basic_string_view s, size_type pos = 0 ) const noexcept;`] +[section `constexpr size_type find_first_not_of( basic_string_view str, size_type pos = 0 ) const noexcept;`] -* *Returns:* `...`. +* *Returns:* The lowest position `i` such that `i >= pos` and the character at position `i` is not equal to one of the characters in `str`, or `npos` if such a position doesn't exist. [endsect] @@ -640,9 +652,9 @@ typedef basic_string_view u8string_view; [section find_last_not_of] -[section `constexpr size_type find_last_not_of( basic_string_view s, size_type pos = npos ) const noexcept;`] +[section `constexpr size_type find_last_not_of( basic_string_view str, size_type pos = npos ) const noexcept;`] -* *Returns:* `...`. +* *Returns:* The highest position `i` such that `i <= pos` and the character at position `i` is not equal to one of the characters in `str`, or `npos` if such a position doesn't exist. [endsect] @@ -733,6 +745,9 @@ typedef basic_string_view u8string_view; [section Stream Inserter] [section `template std::basic_ostream& operator<<( std::basic_ostream& os, basic_string_view str );`] + +* *Effects:* equivalent to `os << x`, where `x` is a pointer to a null-terminated character sequence with the same contents as `*this`. + [endsect] [endsect] From 3cec50846092ba663c64bf72ff0438e29254d18b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 10 Oct 2021 02:25:50 +0300 Subject: [PATCH 080/258] Update string_view.qbk --- doc/string_view.qbk | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/doc/string_view.qbk b/doc/string_view.qbk index 5d8c8f7..330ee39 100644 --- a/doc/string_view.qbk +++ b/doc/string_view.qbk @@ -133,7 +133,7 @@ public: constexpr size_type find( basic_string_view str, size_type pos = 0 ) const noexcept; constexpr size_type find( Ch c, size_type pos = 0 ) const noexcept; - constexpr size_type find( Ch const* s, size_type pos, size_type n ) const; + constexpr size_type find( Ch const* s, size_type pos, size_type n ) const noexcept; constexpr size_type find( Ch const* s, size_type pos = 0 ) const noexcept; // rfind @@ -291,13 +291,13 @@ typedef basic_string_view u8string_view; [section `constexpr const_reverse_iterator rbegin() const noexcept;`] -* *Returns:* `std::make_reverse_iterator( end() )`. +* *Returns:* `const_reverse_iterator( end() )`. [endsect] [section `constexpr const_reverse_iterator rend() const noexcept;`] -* *Returns:* `std::make_reverse_iterator( begin() )`. +* *Returns:* `const_reverse_iterator( begin() )`. [endsect] @@ -384,12 +384,23 @@ typedef basic_string_view u8string_view; [section Modifiers] [section `constexpr void remove_prefix( size_type n ) noexcept;`] + +* *Requires:* `n <= size()`. +* *Effects:* advances `data()` by `n` and decreases `size()` by `n`. + [endsect] [section `constexpr void remove_suffix( size_type n ) noexcept;`] + +* *Requires:* `n <= size()`. +* *Effects:* decreases `size()` by `n`. + [endsect] [section `constexpr void swap( basic_string_view& s ) noexcept;`] + +* *Effects:* exchanges the contents of `*this` and `s`. + [endsect] [endsect] @@ -411,7 +422,7 @@ typedef basic_string_view u8string_view; [section `constexpr basic_string_view substr( size_type pos = 0, size_type n = npos ) const;`] -* *Returns:* A `basic_string_view` object `r` such that `r.data() == data() + pos` and `r.size() == std::min( size() - pos, n )`. +* *Returns:* `basic_string_view( data() + pos, std::min( size() - pos, n ) )`. * *Throws:* `std::out_of_range` when `pos >= size()`. [endsect] From 5d7b469e29affb283796b1a0415e856ee232b6d4 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 10 Oct 2021 03:09:53 +0300 Subject: [PATCH 081/258] Improve .find --- include/boost/core/string_view.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index 30186e9..05c7393 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -640,20 +640,21 @@ public: BOOST_CXX14_CONSTEXPR size_type find( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT { + if( n == 1 ) return find( s[0], pos ); + if( pos + n > size() ) return npos; if( n == 0 ) return pos; Ch const* p = data() + pos; - Ch const* last = data() + size(); + Ch const* last = data() + size() - n + 1; for( ;; ) { p = traits_type::find( p, last - p, s[0] ); if( p == 0 ) break; - if( static_cast( last - p ) < n ) break; - if( traits_type::compare( p, s, n ) == 0 ) return p - data(); + if( traits_type::compare( p + 1, s + 1, n - 1 ) == 0 ) return p - data(); ++p; } From 220d4ae0a9e50a314a2d8c693a8ae45bd1ad40d6 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 10 Oct 2021 17:47:57 +0300 Subject: [PATCH 082/258] Improve starts_with/ends_with --- include/boost/core/string_view.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/core/string_view.hpp b/include/boost/core/string_view.hpp index 05c7393..3c35c48 100644 --- a/include/boost/core/string_view.hpp +++ b/include/boost/core/string_view.hpp @@ -592,7 +592,7 @@ public: BOOST_CONSTEXPR bool starts_with( basic_string_view x ) const BOOST_NOEXCEPT { - return substr( 0, x.size() ) == x; + return size() >= x.size() && traits_type::compare( data(), x.data(), x.size() ) == 0; } BOOST_CONSTEXPR bool starts_with( Ch x ) const BOOST_NOEXCEPT @@ -609,7 +609,7 @@ public: BOOST_CONSTEXPR bool ends_with( basic_string_view x ) const BOOST_NOEXCEPT { - return size() >= x.size() && compare( size() - x.size(), npos, x ) == 0; + return size() >= x.size() && traits_type::compare( data() + size() - x.size(), x.data(), x.size() ) == 0; } BOOST_CONSTEXPR bool ends_with( Ch x ) const BOOST_NOEXCEPT From bfeee019ddf5373ab35775307a111cbf085fb665 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 10 Oct 2021 18:20:46 +0300 Subject: [PATCH 083/258] Update revision history --- doc/changes.qbk | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/doc/changes.qbk b/doc/changes.qbk index f1b877a..f4b48dc 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -10,7 +10,10 @@ * Added a generic implementation to `boost/core/cmath.hpp`, enabled when `BOOST_CORE_USE_GENERIC_CMATH` is defined or when the platform does not provide the necessary facilities in ``. -* Added `boost::core::type_name`. +* Added `boost::core::type_name`, a utility function that returns the name of a type as a string. +* Added `boost::core::string_view`, a portable implementation of C++17's `std::string_view` that differs + from `boost::string_view` by supporting implicit conversions from and to `std::string_view`, when that + is available. [endsect] @@ -22,11 +25,11 @@ [section Changes in 1.76.0] -* Add implicit conversion between compatible reference wrappers. -* Add `boost/core/cmath.hpp`, a portable implementation of the floating point classification functions from ``. -* Add `boost/core/bit.hpp`, a portable implementation of the C++20 standard header ``. -* Fix `BOOST_TEST_EQ`, `BOOST_TEST_NE` for character types under C++20. -* Revise allocator access utilities (now support VS2013, and no workarounds use `allocator_traits`.) +* Added implicit conversion between compatible reference wrappers. +* Added `boost/core/cmath.hpp`, a portable implementation of the floating point classification functions from ``. +* Added `boost/core/bit.hpp`, a portable implementation of the C++20 standard header ``. +* Fixed `BOOST_TEST_EQ`, `BOOST_TEST_NE` for character types under C++20. +* Revised allocator access utilities (now support VS2013, and no workarounds use `allocator_traits`.) [endsect] From ce912859aa9a6b4a6ab360ae8d5acfc0caab5b0c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 10 Oct 2021 18:22:08 +0300 Subject: [PATCH 084/258] Change cancel-in-progress to false in ci.yml --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 718317c..bfb5bfb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ on: concurrency: group: ${{format('{0}:{1}', github.repository, github.ref)}} - cancel-in-progress: true + cancel-in-progress: false env: GIT_FETCH_JOBS: 8 From 773499db5ee6e4fd14788f3656c516e70b0cfad4 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 10 Oct 2021 18:23:21 +0300 Subject: [PATCH 085/258] Remove concurrency section from ci.yml --- .github/workflows/ci.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bfb5bfb..1ed7a81 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,10 +14,6 @@ on: - develop - feature/** -concurrency: - group: ${{format('{0}:{1}', github.repository, github.ref)}} - cancel-in-progress: false - env: GIT_FETCH_JOBS: 8 NET_RETRY_COUNT: 5 From 0f7d02de01693626a80b5ed993446c375d770863 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 10 Oct 2021 19:29:46 +0300 Subject: [PATCH 086/258] Update revision history --- doc/changes.qbk | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/changes.qbk b/doc/changes.qbk index f4b48dc..c86ae6a 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -38,6 +38,7 @@ * Implemented the allocator access utilities which provide a replacement for `allocator_traits` with individual traits and functions for each facility. They support the C++11 allocator model when possible and provide a fallback for C++98 compatibility. +* Added `BOOST_TEST_WITH` to Lightweight Test. [endsect] From b677d1eeae6b075b001475a21e8000c0d465109b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 10 Oct 2021 18:41:33 +0300 Subject: [PATCH 087/258] Only update the necessary submodules in ci.yml --- .github/workflows/ci.yml | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1ed7a81..885b6a7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -339,7 +339,6 @@ jobs: BUILD_JOBS=$((nproc || sysctl -n hw.ncpu) 2> /dev/null) echo "BUILD_JOBS=$BUILD_JOBS" >> $GITHUB_ENV echo "CMAKE_BUILD_PARALLEL_LEVEL=$BUILD_JOBS" >> $GITHUB_ENV - DEPINST_ARGS=() GIT_VERSION="$(git --version | sed -e 's/git version //')" GIT_HAS_JOBS=1 if [ -f "/etc/debian_version" ] @@ -366,16 +365,23 @@ jobs: fi if [ "$GIT_HAS_JOBS" -ne 0 ] then - DEPINST_ARGS+=("--git_args" "--jobs $GIT_FETCH_JOBS") + GIT_ARGS="--jobs $GIT_FETCH_JOBS" fi cd .. git clone -b "$BOOST_BRANCH" --depth 1 "https://github.com/boostorg/boost.git" "boost-root" cd boost-root mkdir -p libs/$LIBRARY cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY - git submodule update --init tools/boostdep - DEPINST_ARGS+=("$LIBRARY") - python tools/boostdep/depinst/depinst.py "${DEPINST_ARGS[@]}" + git submodule init tools/boost_install + git submodule init libs/headers + git submodule init tools/build + git submodule init tools/cmake + git submodule init libs/assert + git submodule init libs/config + git submodule init libs/static_assert + git submodule init libs/throw_exception + git submodule init libs/type_traits + git submodule update $GIT_ARGS if [ -z "${{matrix.cmake_tests}}" ] then ./bootstrap.sh @@ -493,8 +499,16 @@ jobs: git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root cd boost-root xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\ - git submodule update --init tools/boostdep - python tools/boostdep/depinst/depinst.py --git_args "--jobs %GIT_FETCH_JOBS%" %LIBRARY% + git submodule init tools/boost_install + git submodule init libs/headers + git submodule init tools/build + git submodule init tools/cmake + git submodule init libs/assert + git submodule init libs/config + git submodule init libs/static_assert + git submodule init libs/throw_exception + git submodule init libs/type_traits + git submodule update --jobs %GIT_FETCH_JOBS% cmd /c bootstrap b2 -d0 headers From e02c33370680a86afa4fe998c7097c4482a88a54 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 11 Oct 2021 02:09:45 +0300 Subject: [PATCH 088/258] Update string_view.qbk --- doc/string_view.qbk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/string_view.qbk b/doc/string_view.qbk index 330ee39..27edfeb 100644 --- a/doc/string_view.qbk +++ b/doc/string_view.qbk @@ -757,7 +757,7 @@ typedef basic_string_view u8string_view; [section `template std::basic_ostream& operator<<( std::basic_ostream& os, basic_string_view str );`] -* *Effects:* equivalent to `os << x`, where `x` is a pointer to a null-terminated character sequence with the same contents as `*this`. +* *Effects:* equivalent to `os << x`, where `x` is a pointer to a null-terminated character sequence with the same contents as `str`. [endsect] From fdf1ed78a78f243dd496489d90e0ec59609dd326 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Wed, 13 Oct 2021 08:37:37 -0400 Subject: [PATCH 089/258] Contribute span implementation --- doc/core.qbk | 1 + doc/span.qbk | 405 +++++++++++++++++++++++++++ include/boost/core/span.hpp | 403 +++++++++++++++++++++++++++ test/Jamfile.v2 | 8 + test/as_bytes_test.cpp | 34 +++ test/as_writable_bytes_test.cpp | 34 +++ test/span_constructible_test.cpp | 192 +++++++++++++ test/span_deduction_guide_test.cpp | 109 ++++++++ test/span_test.cpp | 425 +++++++++++++++++++++++++++++ test/span_types_test.cpp | 128 +++++++++ 10 files changed, 1739 insertions(+) create mode 100644 doc/span.qbk create mode 100644 include/boost/core/span.hpp create mode 100644 test/as_bytes_test.cpp create mode 100644 test/as_writable_bytes_test.cpp create mode 100644 test/span_constructible_test.cpp create mode 100644 test/span_deduction_guide_test.cpp create mode 100644 test/span_test.cpp create mode 100644 test/span_types_test.cpp diff --git a/doc/core.qbk b/doc/core.qbk index 9e2c1a5..55101e3 100644 --- a/doc/core.qbk +++ b/doc/core.qbk @@ -65,6 +65,7 @@ criteria for inclusion is that the utility component be: [include quick_exit.qbk] [include ref.qbk] [include scoped_enum.qbk] +[include span.qbk] [include string_view.qbk] [include swap.qbk] [include typeinfo.qbk] diff --git a/doc/span.qbk b/doc/span.qbk new file mode 100644 index 0000000..c6205b8 --- /dev/null +++ b/doc/span.qbk @@ -0,0 +1,405 @@ +[/ +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +] + +[section:span span] + +[simplesect Authors] + +* Glen Fernandes + +[endsimplesect] + +[section Overview] + +This header provides class template `span`, which is a +view over a sequence of objects. It implements the C++20 standard library +`std::span` facility. This implementation supports C++11 and higher. + +In addition to referencing the sequence of objects, the span knows the count of +objects. There are two kinds of spans: + +* Dynamic size (`span` or `span`) +* Static size (`span`) + +Dynamic size spans have a count that can be a value known at run time. Static +size spans have a count that must be known at compile time. + +[endsect] + +[section Examples] + +The following snippet shows a function to compute a SHA1 hash whose parameters +and return type use spans. + +``` +auto sha1(boost::span input, + boost::span ouput) +{ + SHA_CTX context; + SHA1_Init(&context); + SHA1_Update(&context, input.data(), input.size()); + SHA1_Final(output.data(), &context); + return output; +} +``` + +[endsect] + +[section Reference] + +``` +namespace boost { + +constexpr std::size_t dynamic_extent = -1; + +template +class span { +public: + typedef T element_type; + typedef std::remove_cv_t value_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T* iterator; + typedef const T* const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + static constexpr std::size_t extent = E; + + constexpr span() noexcept; + + explicit(E != dynamic_extent) + template + constexpr span(I* f, size_type c); + + explicit(E != dynamic_extent) + template + constexpr span(I* f, L* l); + + template + constexpr span(type_identity_t (&a)[N]); + + template + constexpr span(std::array& a) noexcept; + + template + constexpr span(const std::array& a) noexcept; + + explicit(E != dynamic_extent) + template + constexpr span(R&& r); + + explicit(E != dynamic_extent && N == dynamic_extent) + template + constexpr span(const span& s) noexcept; + + template + constexpr span first() const; + + template + constexpr span last() const; + + template + constexpr span subspan() const; + + constexpr span first(size_type c) const; + constexpr span last(size_type c) const; + + constexpr span subspan(size_type o, + size_type c = dynamic_extent) const; + + constexpr size_type size() const noexcept; + constexpr size_type size_bytes() const noexcept; + constexpr bool empty() const noexcept; + + constexpr reference operator[](size_type i) const; + constexpr reference front() const; + constexpr reference back() const; + constexpr pointer data() const noexcept; + + constexpr iterator begin() const noexcept; + constexpr iterator end() const noexcept; + constexpr reverse_iterator rbegin() const noexcept; + constexpr reverse_iterator rend() const noexcept; + constexpr const_iterator cbegin() const noexcept; + constexpr const_iterator cend() const noexcept; + constexpr const_reverse_iterator crbegin() const noexcept; + constexpr const_reverse_iterator crend() const noexcept; + + friend constexpr iterator begin(span s) noexcept { + return s.begin(); + } + + friend constexpr iterator end(span s) noexcept { + return s.end(); + } +}; + +template +span(I*, L) -> span; + +template +span(T(&)[N]) -> span; + +template +span(std::array&) -> span; + +template +span(const std::array&) -> span; + +template +span(R&&) -> span().data())> >; + +template +span +as_bytes(span s) noexcept; + +template +span +as_writable_bytes(span s) noexcept; + +} /* boost */ +``` + +[section Constructors] + +[variablelist +[[`constexpr span() noexcept;`] +[[variablelist +[[Constraints][`E == dynamic_extent || E == 0` is `true`.]] +[[Postconditions][`size() == 0 && data() == nullptr`.]]]]] +[[`explicit(E != dynamic_extent) +template +constexpr span(I* f, size_type c);`] +[[variablelist +[[Constraints] +[`is_convertible_v` is `true`.]] +[[Preconditions] +[[itemized_list +[`[f, f + c)` is a valid range.] +[If `E` is not equal to `dynamic_extent`, then `c` is equal to `E`.]]]] +[[Effects][Constructs a `span` with data `f` and size `c`.]] +[[Throws][Nothing.]]]]] +[[`explicit(E != dynamic_extent) +template +constexpr span(I* f, L* l);`] +[[variablelist +[[Constraints] +[`is_convertible_v` is `true`.]] +[[Preconditions] +[[itemized_list +[If `E` is not equal to `dynamic_extent`, then `l - f` is equal to `E`.] +[`[f, l)` is a valid range.]]]] +[[Effects][Constructs a `span` with data `f` and size `l - f`.]] +[[Throws][Nothing.]]]]] +[[`template +constexpr span(type_identity_t (&a)[N]);`] +[[variablelist +[[Constraints][`E == dynamic_extent || E == N` is `true`.]] +[[Effects][Constructs a `span` that is a view over the supplied array.]] +[[Postconditions][`size() == N && data() == &a[0]` is `true`.]]]]] +[[`template +constexpr span(std::array& a) noexcept;`] +[[variablelist +[[Constraints] +[[itemized_list +[`E == dynamic_extent || E == N` is `true`, and] +[`U(*)[]` is convertible to `T(*)[]`.]]]] +[[Effects][Constructs a `span` that is a view over the supplied array.]] +[[Postconditions][`size() == N && data() == a.data()` is `true`.]]]]] +[[`template +constexpr span(const std::array& a) noexcept;`] +[[variablelist +[[Constraints] +[[itemized_list +[`E == dynamic_extent || E == N` is `true`, and] +[`U(*)[]` is convertible to `T(*)[]`.]]]] +[[Effects][Constructs a `span` that is a view over the supplied array.]] +[[Postconditions][`size() == N && data() == a.data()` is `true`.]]]]] +[[`explicit(E != dynamic_extent) +template +constexpr span(R&& r);`] +[[variablelist +[[Constraints] +[[itemized_list +[`is_lvalue_reference_v || is_const_v` is `true`] +[`remove_cvref_t` is not a specialization of `span`,] +[`remove_cvref_t` is not a specialization of `array`,] +[`is_array_v>` is `false`,] +[`r.data()` is well-formed and +`is_convertible_v().data())>(*)[], +T(*)[]>` is `true`, and] +[`r.size()` is well-formed and +`is_convertible_v().size()), size_t>` is `true`.]]]] +[[Effects][Constructs a `span` with data `r.data()` and size `r.size()`.]] +[[Throws][What and when r.data() and r.size() throw.]]]]] +[[`explicit(E != dynamic_extent && N == dynamic_extent) +template +constexpr span(const span& s) noexcept;`] +[[variablelist +[[Constraints] +[[itemized_list +[`E == dynamic_extent || N == dynamic_extent || E == N` is `true`, and] +[`is_convertible_v` is `true`.]]]] +[[Preconditions] +[If `E` is not equal to `dynamic_extent`, then `s.size()` is equal to `E`.]] +[[Effects] +[Constructs a `span` that is a view over the range +`[s.data(), s.data() + s.size())`.]] +[[Postconditions][`size() == s.size() && data() == s.data()`.]]]]]] + +[endsect] + +[section Subviews] + +[variablelist +[[`template constexpr span first() const;`] +[[variablelist +[[Mandates][`C <= E` is `true`.]] +[[Preconditions][`C <= size()` is `true`.]] +[[Effects] +[Equivalent to `return R{data(), C};` where `R` is the return type.]]]]] +[[`template constexpr span last() const;`] +[[variablelist +[[Mandates][`C <= E` is `true`.]] +[[Preconditions][`C <= size()` is `true`.]] +[[Effects] +[Equivalent to `return R{data() + (size() - C), C};` where `R` is the return +type.]]]]] +[[`template +constexpr span subspan() const;`] +[[variablelist +[[Mandates][`O <= E && (C == dynamic_extent || C <= E - O)` is `true`.]] +[[Preconditions] +[`O <= size() && (C == dynamic_extent || C <= size() - O)` is `true`.]] +[[Effects] +[Equivalent to +`return span(data() + O, +C != dynamic_extent ? C : size() - O);`.]] +[[Remarks] +[The second template argument of the returned span type is: +`C != dynamic_extent ? C : (E != dynamic_extent ? E - O : +dynamic_extent)`]]]]] +[[`constexpr span first(size_type c) const;`] +[[variablelist +[[Preconditions][`c <= size()` is `true`.]] +[[Effects][Equivalent to: `return {data(), c};`]]]]] +[[`constexpr span last(size_type c) const;`] +[[variablelist +[[Preconditions][`c <= size()` is `true`.]] +[[Effects][Equivalent to: `return {data() + (size() - c), c};`]]]]] +[[`constexpr span subspan(size_type o, +size_type c = dynamic_extent) const;`] +[[variablelist +[[Preconditions] +[`o <= size() && (c == dynamic_extent || o + c <= size())` is `true`.]] +[[Effects] +[Equivalent to: +`return {data() + o, c == dynamic_extent ? size() - o : c};`]]]]]] + +[endsect] + +[section Observers] + +[variablelist +[[`constexpr size_type size() const noexcept;`] +[[variablelist +[[Returns][The number of elements in the span.]]]]] +[[`constexpr size_type size_bytes() const noexcept;`] +[[variablelist +[[Effects][Equivalent to: `return size() * sizeof(T);`]]]]] +[[`constexpr bool empty() const noexcept;`] +[[variablelist +[[Effects][Equivalent to: `return size() == 0;`]]]]]] + +[endsect] + +[section Element access] + +[variablelist +[[`constexpr reference operator[](size_type i) const;`] +[[variablelist +[[Preconditions][`i < size()` is `true`.]] +[[Effects][Equivalent to: `return *(data() + i);`]]]]] +[[`constexpr reference front() const;`] +[[variablelist +[[Preconditions][`empty()` is `false`.]] +[[Effects][Equivalent to: `return *data();`]]]]] +[[`constexpr reference back() const;`] +[[variablelist +[[Preconditions][`empty()` is `false`.]] +[[Effects][Equivalent to: `return *(data() + (size() - 1);`]]]]] +[[`constexpr pointer data() const noexcept;`] +[[variablelist +[[Returns][A pointer to the first element in the span.]]]]]] + +[endsect] + +[section Iterator support] + +[variablelist +[[`constexpr iterator begin() const noexcept;`] +[[variablelist +[[Returns][A constant iterator referring to the first element in the span. If `empty()`, +then it returns the same value as `cend()`.]]]]] +[[`constexpr iterator end() const noexcept;`] +[[variablelist +[[Returns][A constant iterator which is the past-the-end value.]]]]] +[[`constexpr reverse_iterator rbegin() const noexcept;`] +[[variablelist +[[Effects][Equivalent to: `return reverse_iterator(end());`]]]]] +[[`constexpr reverse_iterator rend() const noexcept;`] +[[variablelist +[[Effects][Equivalent to: `return reverse_iterator(begin());`]]]]] +[[`constexpr const_iterator cbegin() const noexcept;`] +[[variablelist +[[Returns] +[A constant iterator referring to the first element in the span. If `empty()`, +then it returns the same value as `cend()`.]]]]] +[[`constexpr const_iterator cend() const noexcept;`] +[[variablelist +[[Returns][A constant iterator which is the past-the-end value.]]]]] +[[`constexpr const_reverse_iterator crbegin() const noexcept;`] +[[variablelist +[[Effects][Equivalent to: `return const_reverse_iterator(cend());`]]]]] +[[`constexpr const_reverse_iterator crend() const noexcept;`] +[[variablelist +[[Effects] +[Equivalent to: `return const_reverse_iterator(cbegin());`]]]]]] + +[endsect] + +[section Views of object representation] + +[variablelist +[[`template +span +as_bytes(span s) noexcept;`] +[[variablelist +[[Effects] +[Equivalent to: +`return {reinterpret_cast(s.data()), s.size_bytes()};`.]]]]] +[[`template +span +as_writable_bytes(span s) noexcept;`] +[[variablelist +[[Constraints][`is_const_v` is `false`.]] +[[Effects] +[Equivalent to: `return R{reinterpret_cast(s.data()), s.size_bytes()};` +where `R` is the return type.]] +[[Returns][`false`.]]]]]] + +[endsect] + +[endsect] + +[endsect] diff --git a/include/boost/core/span.hpp b/include/boost/core/span.hpp new file mode 100644 index 0000000..bafb286 --- /dev/null +++ b/include/boost/core/span.hpp @@ -0,0 +1,403 @@ +/* +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_CORE_SPAN_HPP +#define BOOST_CORE_SPAN_HPP + +#include +#include +#include +#include + +namespace boost { + +constexpr std::size_t dynamic_extent = -1; + +template +class span; + +namespace detail { + +template +struct span_convertible { + static constexpr bool value = std::is_convertible::value; +}; + +template +struct span_capacity { + static constexpr bool value = E == boost::dynamic_extent || E == N; +}; + +template +struct span_compatible { + static constexpr bool value = span_capacity::value && + span_convertible::value; +}; + +template +struct span_uncvref { + typedef typename std::remove_cv::type>::type type; +}; + +template +struct span_is_span { + static constexpr bool value = false; +}; + +template +struct span_is_span > { + static constexpr bool value = true; +}; + +template +struct span_is_array { + static constexpr bool value = false; +}; + +template +struct span_is_array > { + static constexpr bool value = true; +}; + +template +struct span_data { }; + +template +struct span_data().data())>::value>::type> { + typedef typename std::remove_pointer().data())>::type type; +}; + +template +struct span_has_data { + static constexpr bool value = false; +}; + +template +struct span_has_data::type, T>::value>::type> { + static constexpr bool value = true; +}; + +template +struct span_has_size { + static constexpr bool value = false; +}; + +template +struct span_has_size().size()), + std::size_t>::value>::type> { + static constexpr bool value = true; +}; + +template +struct span_is_range { + static constexpr bool value = (std::is_const::value || + std::is_lvalue_reference::value) && + !span_is_span::type>::value && + !span_is_array::type>::value && + !std::is_array::type>::value && + span_has_data::value && + span_has_size::value; +}; + +template +struct span_implicit { + static constexpr bool value = E == boost::dynamic_extent || + N != boost::dynamic_extent; +}; + +template +struct span_copyable { + static constexpr bool value = (N == boost::dynamic_extent || + span_capacity::value) && span_convertible::value; +}; + +template +struct span_sub { + static constexpr std::size_t value = E == boost::dynamic_extent ? + boost::dynamic_extent : E - O; +}; + +template +struct span_store { + constexpr span_store(T* p_, std::size_t) noexcept + : p(p_) { } + static constexpr std::size_t n = E; + T* p; +}; + +template +struct span_store { + constexpr span_store(T* p_, std::size_t n_) noexcept + : p(p_) + , n(n_) { } + T* p; + std::size_t n; +}; + +template +struct span_bytes { + static constexpr std::size_t value = E == boost::dynamic_extent ? + boost::dynamic_extent : sizeof(T) * E; +}; + +} /* detail */ + +template +class span { +public: + typedef T element_type; + typedef typename std::remove_cv::type value_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T* iterator; + typedef const T* const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + static constexpr std::size_t extent = E; + + template::type = 0> + constexpr span() noexcept + : s_(0, 0) { } + + template::value, int>::type = 0> + constexpr span(I* f, size_type c) + : s_(f, c) { } + + template::value, int>::type = 0> + explicit constexpr span(I* f, size_type c) + : s_(f, c) { } + + template::value, int>::type = 0> + constexpr span(I* f, L* l) + : s_(f, l - f) { } + + template::value, int>::type = 0> + explicit constexpr span(I* f, L* l) + : s_(f, l - f) { } + + template::value, + int>::type = 0> + constexpr span(typename std::enable_if::type (&a)[N]) noexcept + : s_(a, N) { } + + template::value, + int>::type = 0> + constexpr span(std::array& a) noexcept + : s_(a.data(), N) { } + + template::value, int>::type = 0> + constexpr span(const std::array& a) noexcept + : s_(a.data(), N) { } + + template::value, int>::type = 0> + constexpr span(R&& r) noexcept(noexcept(r.data()) && noexcept(r.size())) + : s_(r.data(), r.size()) { } + + template::value, int>::type = 0> + explicit constexpr span(R&& r) noexcept(noexcept(r.data()) && + noexcept(r.size())) + : s_(r.data(), r.size()) { } + + template::value && + detail::span_copyable::value, int>::type = 0> + constexpr span(const span& s) noexcept + : s_(s.data(), s.size()) { } + + template::value && + detail::span_copyable::value, int>::type = 0> + explicit constexpr span(const span& s) noexcept + : s_(s.data(), s.size()) { } + + template + constexpr span first() const { + static_assert(C <= E, "Count <= Extent"); + return span(s_.p, C); + } + + template + constexpr span last() const { + static_assert(C <= E, "Count <= Extent"); + return span(s_.p + (s_.n - C), C); + } + + template + constexpr typename std::enable_if::value> >::type subspan() const { + static_assert(O <= E, "Offset <= Extent"); + return span::value>(s_.p + O, s_.n - O); + } + + template + constexpr typename std::enable_if >::type subspan() const { + static_assert(O <= E && C <= E - O, + "Offset <= Extent && Count <= Extent - Offset"); + return span(s_.p + O, C); + } + + constexpr span first(size_type c) const { + return span(s_.p, c); + } + + constexpr span last(size_type c) const { + return span(s_.p + (s_.n - c), c); + } + + constexpr span subspan(size_type o, + size_type c = dynamic_extent) const { + return span(s_.p + o, + c == dynamic_extent ? s_.n - o : c); + } + + constexpr size_type size() const noexcept { + return s_.n; + } + + constexpr size_type size_bytes() const noexcept { + return s_.n * sizeof(T); + } + + constexpr bool empty() const noexcept { + return s_.n == 0; + } + + constexpr reference operator[](size_type i) const { + return s_.p[i]; + } + + constexpr reference front() const { + return *s_.p; + } + + constexpr reference back() const { + return s_.p[s_.n - 1]; + } + + constexpr pointer data() const noexcept { + return s_.p; + } + + constexpr iterator begin() const noexcept { + return s_.p; + } + + constexpr iterator end() const noexcept { + return s_.p + s_.n; + } + + constexpr reverse_iterator rbegin() const noexcept { + return reverse_iterator(s_.p + s_.n); + } + + constexpr reverse_iterator rend() const noexcept { + return reverse_iterator(s_.p); + } + + constexpr const_iterator cbegin() const noexcept { + return s_.p; + } + + constexpr const_iterator cend() const noexcept { + return s_.p + s_.n; + } + + constexpr const_reverse_iterator crbegin() const noexcept { + return const_reverse_iterator(s_.p + s_.n); + } + + constexpr const_reverse_iterator crend() const noexcept { + return const_reverse_iterator(s_.p); + } + + friend constexpr iterator begin(span s) noexcept { + return s.begin(); + } + + friend constexpr iterator end(span s) noexcept { + return s.end(); + } + +private: + detail::span_store s_; +}; + +template +constexpr std::size_t span::extent; + +#ifdef __cpp_deduction_guides +template +span(I*, L) -> span; + +template +span(T(&)[N]) -> span; + +template +span(std::array&) -> span; + +template +span(const std::array&) -> span; + +template +span(R&&) -> span::type>; + +template +span(span) -> span; +#endif + +#ifdef __cpp_lib_byte +template +inline span::value> +as_bytes(span s) noexcept +{ + return span::value>(reinterpret_cast(s.data()), + s.size_bytes()); +} + +template +inline typename std::enable_if::value, + span::value> >::type +as_writable_bytes(span s) noexcept +{ + return span::value>(reinterpret_cast(s.data()), s.size_bytes()); +} +#endif + +} /* boost */ + +#endif diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 7a1912c..6ebefb6 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -8,6 +8,7 @@ import modules ; import testing ; +import ../../config/checks/config : requires ; # quick test (for CI) run quick.cpp ; @@ -269,5 +270,12 @@ run sv_lt_test.cpp ; run sv_stream_insert_test.cpp ; run sv_conversion_test.cpp ; +run span_test.cpp : : : [ requires cxx11_constexpr cxx11_decltype ] ; +run span_types_test.cpp : : : [ requires cxx11_constexpr cxx11_decltype ] ; +run span_constructible_test.cpp : : : [ requires cxx11_constexpr cxx11_decltype ] ; +run span_deduction_guide_test.cpp : : : [ requires cpp_deduction_guides ] ; +run as_bytes_test.cpp : : : [ requires cpp_lib_byte ] ; +run as_writable_bytes_test.cpp : : : [ requires cpp_lib_byte ] ; + use-project /boost/core/swap : ./swap ; build-project ./swap ; diff --git a/test/as_bytes_test.cpp b/test/as_bytes_test.cpp new file mode 100644 index 0000000..e99ef5d --- /dev/null +++ b/test/as_bytes_test.cpp @@ -0,0 +1,34 @@ +/* +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include + +void test_dynamic() +{ + int a[4]; + boost::span s = + boost::as_bytes(boost::span(&a[0], 4)); + BOOST_TEST_EQ(s.data(), reinterpret_cast(&a[0])); + BOOST_TEST_EQ(s.size(), sizeof(int) * 4); +} + +void test_static() +{ + int a[4]; + boost::span s = + boost::as_bytes(boost::span(&a[0], 4)); + BOOST_TEST_EQ(s.data(), reinterpret_cast(&a[0])); + BOOST_TEST_EQ(s.size(), sizeof(int) * 4); +} + +int main() +{ + test_dynamic(); + test_static(); + return boost::report_errors(); +} diff --git a/test/as_writable_bytes_test.cpp b/test/as_writable_bytes_test.cpp new file mode 100644 index 0000000..47914d8 --- /dev/null +++ b/test/as_writable_bytes_test.cpp @@ -0,0 +1,34 @@ +/* +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include + +void test_dynamic() +{ + int a[4]; + boost::span s = + boost::as_writable_bytes(boost::span(&a[0], 4)); + BOOST_TEST_EQ(s.data(), reinterpret_cast(&a[0])); + BOOST_TEST_EQ(s.size(), sizeof(int) * 4); +} + +void test_static() +{ + int a[4]; + boost::span s = + boost::as_writable_bytes(boost::span(&a[0], 4)); + BOOST_TEST_EQ(s.data(), reinterpret_cast(&a[0])); + BOOST_TEST_EQ(s.size(), sizeof(int) * 4); +} + +int main() +{ + test_dynamic(); + test_static(); + return boost::report_errors(); +} diff --git a/test/span_constructible_test.cpp b/test/span_constructible_test.cpp new file mode 100644 index 0000000..857eada --- /dev/null +++ b/test/span_constructible_test.cpp @@ -0,0 +1,192 @@ +/* +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include + +template +struct range { + T* data() { + return 0; + } + + const T* data() const { + return 0; + } + + std::size_t size() const { + return 0; + } +}; + +struct base { }; + +struct derived + : base { }; + +void test_default() +{ + BOOST_TEST_TRAIT_TRUE((std::is_default_constructible< + boost::span >)); + BOOST_TEST_TRAIT_TRUE((std::is_default_constructible< + boost::span >)); + BOOST_TEST_TRAIT_FALSE((std::is_default_constructible< + boost::span >)); +} + +void test_data_size() +{ + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + int*, std::size_t>)); + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + int*, std::size_t>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + int, std::size_t>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + const int*, std::size_t>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + derived*, std::size_t>)); +} + +void test_first_last() +{ + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + int*, int*>)); + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + int*, const int*>)); + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + int*, int*>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + int, int*>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + const int*, int*>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + derived*, derived*>)); +} + +void test_array() +{ + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + int(&)[4]>)); + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + int(&)[4]>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + int(&)[4]>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + int(&)[2]>)); +} + +void test_std_array() +{ + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + std::array&>)); + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + std::array&>)); + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + std::array&>)); + BOOST_TEST_TRAIT_TRUE((std::is_constructible, std::array&>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + std::array&>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + std::array&>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + std::array&>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + std::array&>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + std::array&>)); +} + +void test_const_std_array() +{ + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + const std::array >)); + BOOST_TEST_TRAIT_TRUE((std::is_constructible, const std::array >)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + const std::array >)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, const std::array >)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, const std::array >)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + const std::array >)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, const std::array >)); +} + +void test_range() +{ + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + range&>)); + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + range&>)); + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + range >)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + int*>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + range >)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + const range&>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + range&>)); +} + +void test_span() +{ + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + boost::span >)); + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + boost::span >)); + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + boost::span >)); + BOOST_TEST_TRAIT_TRUE((std::is_constructible, boost::span >)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + boost::span >)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + boost::span >)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + boost::span >)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + boost::span >)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + boost::span >)); +} + +void test_copy() +{ + BOOST_TEST_TRAIT_TRUE((std::is_copy_constructible< + boost::span >)); + BOOST_TEST_TRAIT_TRUE((std::is_copy_constructible< + boost::span >)); +} + +void test_assign() +{ + BOOST_TEST_TRAIT_TRUE((std::is_copy_assignable< + boost::span >)); + BOOST_TEST_TRAIT_TRUE((std::is_copy_assignable< + boost::span >)); +} + +int main() +{ + test_default(); + test_data_size(); + test_first_last(); + test_array(); + test_std_array(); + test_const_std_array(); + test_range(); + test_span(); + test_copy(); + test_assign(); + return boost::report_errors(); +} diff --git a/test/span_deduction_guide_test.cpp b/test/span_deduction_guide_test.cpp new file mode 100644 index 0000000..c627ba8 --- /dev/null +++ b/test/span_deduction_guide_test.cpp @@ -0,0 +1,109 @@ +/* +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include + +template +class range { +public: + T* data() { + return &v_[0]; + } + + std::size_t size() const { + return 4; + } + +private: + T v_[4]; +}; + +void test_data_size() +{ + int a[4]; + boost::span s(&a[0], 4); + BOOST_TEST_EQ(s.extent, boost::dynamic_extent); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_first_last() +{ + int a[4]; + boost::span s(&a[0], &a[4]); + BOOST_TEST_EQ(s.extent, boost::dynamic_extent); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_array() +{ + int a[4]; + boost::span s(a); + BOOST_TEST_EQ(s.extent, 4); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_std_array() +{ + std::array a; + boost::span s(a); + BOOST_TEST_EQ(s.extent, 4); + BOOST_TEST_EQ(s.data(), a.data()); + BOOST_TEST_EQ(s.size(), a.size()); +} + +void test_const_std_array() +{ + const std::array a = std::array(); + boost::span s(a); + BOOST_TEST_EQ(s.extent, 4); + BOOST_TEST_EQ(s.data(), a.data()); + BOOST_TEST_EQ(s.size(), a.size()); +} + +void test_range() +{ + range c; + boost::span s(c); + BOOST_TEST_EQ(s.extent, boost::dynamic_extent); + BOOST_TEST_EQ(s.data(), c.data()); + BOOST_TEST_EQ(s.size(), c.size()); +} + +void test_span_dynamic() +{ + int a[4]; + boost::span s(boost::span(&a[0], 4)); + BOOST_TEST_EQ(s.extent, boost::dynamic_extent); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_span_static() +{ + int a[4]; + boost::span s(boost::span(&a[0], 4)); + BOOST_TEST_EQ(s.extent, 4); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +int main() +{ + test_data_size(); + test_first_last(); + test_array(); + test_std_array(); + test_const_std_array(); + test_range(); + test_span_dynamic(); + test_span_static(); + return boost::report_errors(); +} diff --git a/test/span_test.cpp b/test/span_test.cpp new file mode 100644 index 0000000..5ef1d22 --- /dev/null +++ b/test/span_test.cpp @@ -0,0 +1,425 @@ +/* +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include + +template +class range { +public: + T* data() { + return &v_[0]; + } + + std::size_t size() const { + return 4; + } + +private: + T v_[4]; +}; + +void test_extent() +{ + BOOST_TEST_EQ(boost::span::extent, + boost::dynamic_extent); + BOOST_TEST_EQ((boost::span::extent), 2); +} + +void test_default_construct_dynamic() +{ + boost::span s; + BOOST_TEST_EQ(s.data(), static_cast(0)); + BOOST_TEST_EQ(s.size(), 0); +} + +void test_default_construct_static() +{ + boost::span s; + BOOST_TEST_EQ(s.data(), static_cast(0)); + BOOST_TEST_EQ(s.size(), 0); +} + +void test_construct_data_size() +{ + int a[4]; + boost::span s(&a[0], 4); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_construct_first_last() +{ + int a[4]; + boost::span s(&a[0], &a[4]); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_construct_array_dynamic() +{ + int a[4]; + boost::span s(a); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_construct_array_static() +{ + int a[4]; + boost::span s(a); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_construct_std_array_dynamic() +{ + std::array a; + boost::span s(a); + BOOST_TEST_EQ(s.data(), a.data()); + BOOST_TEST_EQ(s.size(), a.size()); +} + +void test_construct_std_array_static() +{ + std::array a; + boost::span s(a); + BOOST_TEST_EQ(s.data(), a.data()); + BOOST_TEST_EQ(s.size(), a.size()); +} + +void test_construct_const_std_array_dynamic() +{ + const std::array a = std::array(); + boost::span s(a); + BOOST_TEST_EQ(s.data(), a.data()); + BOOST_TEST_EQ(s.size(), a.size()); +} + +void test_construct_const_std_array_static() +{ + const std::array a = std::array(); + boost::span s(a); + BOOST_TEST_EQ(s.data(), a.data()); + BOOST_TEST_EQ(s.size(), a.size()); +} + +void test_construct_range() +{ + range c; + boost::span s(c); + BOOST_TEST_EQ(s.data(), c.data()); + BOOST_TEST_EQ(s.size(), c.size()); +} + +void test_construct_span_dynamic() +{ + int a[4]; + boost::span s(boost::span(&a[0], 4)); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_construct_span_dynamic_static() +{ + int a[4]; + boost::span s(boost::span(&a[0], 4)); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_construct_span_static() +{ + int a[4]; + boost::span s(boost::span(&a[0], 4)); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_construct_span_static_dynamic() +{ + int a[4]; + boost::span s(boost::span(&a[0], 4)); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_copy_dynamic() +{ + int a[4]; + boost::span s1(&a[0], 4); + boost::span s2(s1); + BOOST_TEST_EQ(s2.data(), &a[0]); + BOOST_TEST_EQ(s2.size(), 4); +} + +void test_copy_static() +{ + int a[4]; + boost::span s1(&a[0], 4); + boost::span s2(s1); + BOOST_TEST_EQ(s2.data(), &a[0]); + BOOST_TEST_EQ(s2.size(), 4); +} + +void test_assign_dynamic() +{ + boost::span s; + int a[4]; + s = boost::span(&a[0], 4); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_assign_static() +{ + int a1[4]; + boost::span s(&a1[0], 4); + int a2[4]; + s = boost::span(&a2[0], 4); + BOOST_TEST_EQ(s.data(), &a2[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_first() +{ + int a[4]; + boost::span s = boost::span(&a[0], + 4).first<2>(); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 2); +} + +void test_last() +{ + int a[4]; + boost::span s = boost::span(&a[0], 4).last<2>(); + BOOST_TEST_EQ(s.data(), &a[2]); + BOOST_TEST_EQ(s.size(), 2); +} + +void test_subspan_dynamic() +{ + int a[4]; + boost::span s = boost::span(&a[0], 4).subspan<2>(); + BOOST_TEST_EQ(s.data(), &a[2]); + BOOST_TEST_EQ(s.size(), 2); +} + +void test_subspan_static() +{ + int a[4]; + boost::span s = boost::span(&a[0], + 4).subspan<2>(); + BOOST_TEST_EQ(s.data(), &a[2]); + BOOST_TEST_EQ(s.size(), 2); +} + +void test_subspan() +{ + int a[4]; + boost::span s = boost::span(&a[0], + 4).subspan<2, 1>(); + BOOST_TEST_EQ(s.data(), &a[2]); + BOOST_TEST_EQ(s.size(), 1); +} + +void test_first_size() +{ + int a[4]; + boost::span s = boost::span(&a[0], 4).first(2); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 2); +} + +void test_last_size() +{ + int a[4]; + boost::span s = boost::span(&a[0], 4).last(2); + BOOST_TEST_EQ(s.data(), &a[2]); + BOOST_TEST_EQ(s.size(), 2); +} + +void test_subspan_range() +{ + int a[4]; + boost::span s = boost::span(&a[0], 4).subspan(2); + BOOST_TEST_EQ(s.data(), &a[2]); + BOOST_TEST_EQ(s.size(), 2); +} + +void test_subspan_range_count() +{ + int a[4]; + boost::span s = boost::span(&a[0], + 4).subspan(2, 1); + BOOST_TEST_EQ(s.data(), &a[2]); + BOOST_TEST_EQ(s.size(), 1); +} + +void test_size() +{ + int a[4]; + BOOST_TEST_EQ((boost::span(&a[0], 4).size()), 4); +} + +void test_size_bytes() +{ + int a[4]; + BOOST_TEST_EQ((boost::span(&a[0], 4).size_bytes()), + 4 * sizeof(int)); +} + +void test_empty_dynamic() +{ + int a[4]; + BOOST_TEST(boost::span().empty()); + BOOST_TEST_NOT((boost::span(&a[0], 4).empty())); +} + +void test_empty_static() +{ + int a[4]; + BOOST_TEST((boost::span().empty())); + BOOST_TEST_NOT((boost::span(&a[0], 4).empty())); +} + +void test_index() +{ + int a[4] = { 1, 2, 3, 4 }; + BOOST_TEST_EQ((boost::span(&a[0], 4)[2]), 3); +} + +void test_front() +{ + int a[4] = { 1, 2, 3, 4 }; + BOOST_TEST_EQ((boost::span(&a[0], 4).front()), 1); +} + +void test_back() +{ + int a[4] = { 1, 2, 3, 4 }; + BOOST_TEST_EQ((boost::span(&a[0], 4).back()), 4); +} + +void test_data() +{ + int a[4]; + BOOST_TEST_EQ((boost::span(&a[0], 4).data()), &a[0]); +} + +void test_begin() +{ + int a[4]; + BOOST_TEST_EQ((boost::span(&a[0], 4).begin()), &a[0]); +} + +void test_end() +{ + int a[4]; + BOOST_TEST_EQ((boost::span(&a[0], 4).end()), &a[4]); +} + +void test_rbegin() +{ + int a[4]; + BOOST_TEST_EQ((boost::span(&a[0], 4).rbegin().base()), &a[4]); +} + +void test_rend() +{ + int a[4]; + BOOST_TEST_EQ((boost::span(&a[0], 4).rend().base()), &a[0]); +} + +void test_cbegin() +{ + int a[4]; + BOOST_TEST_EQ((boost::span(&a[0], 4).cbegin()), &a[0]); +} + +void test_cend() +{ + int a[4]; + BOOST_TEST_EQ((boost::span(&a[0], 4).cend()), &a[4]); +} + +void test_crbegin() +{ + int a[4]; + BOOST_TEST_EQ((boost::span(&a[0], 4).crbegin().base()), &a[4]); +} + +void test_crend() +{ + int a[4]; + BOOST_TEST_EQ((boost::span(&a[0], 4).crend().base()), &a[0]); +} + +void test_begin_span() +{ + int a[4]; + BOOST_TEST_EQ((begin(boost::span(&a[0], 4))), &a[0]); +} + +void test_end_span() +{ + int a[4]; + BOOST_TEST_EQ((end(boost::span(&a[0], 4))), &a[4]); +} + +int main() +{ + test_extent(); + test_default_construct_dynamic(); + test_default_construct_static(); + test_construct_data_size(); + test_construct_first_last(); + test_construct_array_dynamic(); + test_construct_array_static(); + test_construct_std_array_dynamic(); + test_construct_std_array_static(); + test_construct_const_std_array_dynamic(); + test_construct_const_std_array_static(); + test_construct_range(); + test_construct_span_dynamic(); + test_construct_span_dynamic_static(); + test_construct_span_static(); + test_construct_span_static_dynamic(); + test_copy_dynamic(); + test_copy_static(); + test_assign_dynamic(); + test_assign_static(); + test_first(); + test_last(); + test_subspan_dynamic(); + test_subspan_static(); + test_subspan(); + test_first_size(); + test_last_size(); + test_subspan_range(); + test_subspan_range_count(); + test_size(); + test_size_bytes(); + test_empty_dynamic(); + test_empty_static(); + test_index(); + test_front(); + test_back(); + test_data(); + test_begin(); + test_end(); + test_rbegin(); + test_rend(); + test_cbegin(); + test_cend(); + test_crbegin(); + test_crend(); + test_begin_span(); + test_end_span(); + return boost::report_errors(); +} diff --git a/test/span_types_test.cpp b/test/span_types_test.cpp new file mode 100644 index 0000000..56c7413 --- /dev/null +++ b/test/span_types_test.cpp @@ -0,0 +1,128 @@ +/* +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include + +void test_element_type() +{ + BOOST_TEST_TRAIT_SAME(int, + boost::span::element_type); + BOOST_TEST_TRAIT_SAME(char, + boost::span::element_type); +} + +void test_value_type() +{ + BOOST_TEST_TRAIT_SAME(char, + boost::span::value_type); + BOOST_TEST_TRAIT_SAME(int, + boost::span::value_type); + BOOST_TEST_TRAIT_SAME(int, + boost::span::value_type); + BOOST_TEST_TRAIT_SAME(int, + boost::span::value_type); + BOOST_TEST_TRAIT_SAME(int, + boost::span::value_type); +} + +void test_size_type() +{ + BOOST_TEST_TRAIT_SAME(std::size_t, + boost::span::size_type); + BOOST_TEST_TRAIT_SAME(std::size_t, + boost::span::size_type); +} + +void test_difference_type() +{ + BOOST_TEST_TRAIT_SAME(std::ptrdiff_t, + boost::span::difference_type); + BOOST_TEST_TRAIT_SAME(std::ptrdiff_t, + boost::span::difference_type); +} + +void test_pointer() +{ + BOOST_TEST_TRAIT_SAME(char*, + boost::span::pointer); + BOOST_TEST_TRAIT_SAME(int*, + boost::span::pointer); +} + +void test_const_pointer() +{ + BOOST_TEST_TRAIT_SAME(const char*, + boost::span::const_pointer); + BOOST_TEST_TRAIT_SAME(const int*, + boost::span::const_pointer); +} + +void test_reference() +{ + BOOST_TEST_TRAIT_SAME(char&, + boost::span::reference); + BOOST_TEST_TRAIT_SAME(int&, + boost::span::reference); +} + +void test_const_reference() +{ + BOOST_TEST_TRAIT_SAME(const char&, + boost::span::const_reference); + BOOST_TEST_TRAIT_SAME(const int&, + boost::span::const_reference); +} + +void test_iterator() +{ + BOOST_TEST_TRAIT_SAME(char*, + boost::span::iterator); + BOOST_TEST_TRAIT_SAME(int*, + boost::span::iterator); +} + +void test_const_iterator() +{ + BOOST_TEST_TRAIT_SAME(const char*, + boost::span::const_iterator); + BOOST_TEST_TRAIT_SAME(const int*, + boost::span::const_iterator); +} + +void test_reverse_iterator() +{ + BOOST_TEST_TRAIT_SAME(std::reverse_iterator, + boost::span::reverse_iterator); + BOOST_TEST_TRAIT_SAME(std::reverse_iterator, + boost::span::reverse_iterator); +} + +void test_const_reverse_iterator() +{ + BOOST_TEST_TRAIT_SAME(std::reverse_iterator, + boost::span::const_reverse_iterator); + BOOST_TEST_TRAIT_SAME(std::reverse_iterator, + boost::span::const_reverse_iterator); +} + +int main() +{ + test_element_type(); + test_value_type(); + test_size_type(); + test_difference_type(); + test_pointer(); + test_const_pointer(); + test_reference(); + test_const_reference(); + test_iterator(); + test_const_iterator(); + test_reverse_iterator(); + test_const_reverse_iterator(); + return boost::report_errors(); +} From 62b23df9efa01f1acf299ae5d0deae309f080729 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Fri, 15 Oct 2021 19:00:57 -0400 Subject: [PATCH 090/258] Update revision history --- doc/changes.qbk | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/changes.qbk b/doc/changes.qbk index c86ae6a..6f37292 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -14,6 +14,7 @@ * Added `boost::core::string_view`, a portable implementation of C++17's `std::string_view` that differs from `boost::string_view` by supporting implicit conversions from and to `std::string_view`, when that is available. +* Added `boost::span`, a C++11 implementation of C++20's `std::span`. [endsect] From 0e57df5aab29b1760ad127b2ed7f57ee91527e2d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 16 Oct 2021 17:55:35 +0300 Subject: [PATCH 091/258] Regenerate CMakeLists.txt --- CMakeLists.txt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2110bcc..4a0d81a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,9 @@ -# Copyright 2018, 2019 Peter Dimov +# Generated by `boostdep --cmake core` +# Copyright 2020, 2021 Peter Dimov # Distributed under the Boost Software License, Version 1.0. -# See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt +# https://www.boost.org/LICENSE_1_0.txt -cmake_minimum_required(VERSION 3.5...3.16) +cmake_minimum_required(VERSION 3.5...3.20) project(boost_core VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) @@ -15,9 +16,11 @@ target_link_libraries(boost_core INTERFACE Boost::assert Boost::config + Boost::static_assert + Boost::throw_exception ) -if(BUILD_TESTING) +if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt") add_subdirectory(test) From d5bd40e5280487fb29a108eb42e6c4f0bef690d8 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 16 Oct 2021 18:10:13 +0300 Subject: [PATCH 092/258] Update test/Jamfile and test/CMakeLists.txt so that missing dependencies are caught --- test/CMakeLists.txt | 19 +++++++++++++++++-- test/Jamfile.v2 | 18 +++++++++--------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 82f1b33..4f85621 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2018, 2019 Peter Dimov +# Copyright 2018, 2019, 2021 Peter Dimov # Distributed under the Boost Software License, Version 1.0. # See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt @@ -6,7 +6,22 @@ include(BoostTestJamfile OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST) if(HAVE_BOOST_TEST) -boost_test_jamfile(FILE Jamfile.v2 LINK_LIBRARIES Boost::core Boost::static_assert Boost::type_traits Boost::throw_exception) +boost_test_jamfile(FILE Jamfile.v2 LINK_LIBRARIES Boost::core Boost::static_assert) + +set(BOOST_TEST_LINK_LIBRARIES Boost::core Boost::type_traits) + +boost_test(TYPE run SOURCES eif_constructors.cpp) +boost_test(TYPE run SOURCES eif_dummy_arg_disambiguation.cpp) +boost_test(TYPE run SOURCES eif_lazy.cpp) +boost_test(TYPE run SOURCES eif_lazy_test.cpp) +boost_test(TYPE run SOURCES eif_member_templates.cpp) +boost_test(TYPE run SOURCES eif_namespace_disambiguation.cpp) +boost_test(TYPE run SOURCES eif_no_disambiguation.cpp) +boost_test(TYPE run SOURCES eif_partial_specializations.cpp) + +set(BOOST_TEST_LINK_LIBRARIES Boost::core Boost::throw_exception) + +boost_test(TYPE run SOURCES no_exceptions_support_test.cpp) endif() diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 6ebefb6..f645a07 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -41,14 +41,14 @@ compile-fail ref_implicit_fail4.cpp ; run ref_cv_test.cpp ; run ref_conversion_test.cpp ; -run eif_constructors.cpp ; -run eif_dummy_arg_disambiguation.cpp ; -run eif_lazy.cpp ; -run eif_lazy_test.cpp ; -run eif_member_templates.cpp ; -run eif_namespace_disambiguation.cpp ; -run eif_no_disambiguation.cpp ; -run eif_partial_specializations.cpp ; +run eif_constructors.cpp : ; +run eif_dummy_arg_disambiguation.cpp : ; +run eif_lazy.cpp : ; +run eif_lazy_test.cpp : ; +run eif_member_templates.cpp : ; +run eif_namespace_disambiguation.cpp : ; +run eif_no_disambiguation.cpp : ; +run eif_partial_specializations.cpp : ; compile-fail noncopyable_compile_fail.cpp ; @@ -229,7 +229,7 @@ run uncaught_exceptions.cpp run uncaught_exceptions_np.cpp : : : on ; -run no_exceptions_support_test.cpp ; +run no_exceptions_support_test.cpp : ; run no_exceptions_support_test.cpp : : : off : no_exceptions_support_test_nx ; run cmath_test.cpp ; From 5cf3569218b8dc12c7b23b1ccf3a033a1868a54d Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Wed, 20 Oct 2021 22:26:25 -0400 Subject: [PATCH 093/258] Correct documentation --- doc/span.qbk | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/span.qbk b/doc/span.qbk index c6205b8..7d8d3e3 100644 --- a/doc/span.qbk +++ b/doc/span.qbk @@ -395,8 +395,7 @@ as_writable_bytes(span s) noexcept;`] [[Constraints][`is_const_v` is `false`.]] [[Effects] [Equivalent to: `return R{reinterpret_cast(s.data()), s.size_bytes()};` -where `R` is the return type.]] -[[Returns][`false`.]]]]]] +where `R` is the return type.]]]]]] [endsect] From cbf03c4b9ca19cc1f16918671542e68d64d90431 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 26 Oct 2021 00:54:37 +0300 Subject: [PATCH 094/258] Add msvc-14.3 to GHA --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 885b6a7..705e8a0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -472,6 +472,10 @@ jobs: cxxstd: "14,17,latest" addrmd: 32,64 os: windows-2019 + - toolset: msvc-14.3 + cxxstd: "14,17,latest" + addrmd: 32,64 + os: windows-2022 - toolset: gcc cxxstd: "03,11,14,17,2a" addrmd: 64 From 8942e8ecc9cc3494a93fb9919b0df1802ae650ea Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 26 Oct 2021 01:00:15 +0300 Subject: [PATCH 095/258] Update cmake_subdir_test/CMakeLists.txt --- test/cmake_subdir_test/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/cmake_subdir_test/CMakeLists.txt b/test/cmake_subdir_test/CMakeLists.txt index 8fee7b3..c8eac57 100644 --- a/test/cmake_subdir_test/CMakeLists.txt +++ b/test/cmake_subdir_test/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2018, 2019 Peter Dimov +# Copyright 2018, 2019, 2021 Peter Dimov # Distributed under the Boost Software License, Version 1.0. # See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt @@ -9,6 +9,8 @@ project(cmake_subdir_test LANGUAGES CXX) add_subdirectory(../.. boostorg/core) add_subdirectory(../../../assert boostorg/assert) add_subdirectory(../../../config boostorg/config) +add_subdirectory(../../../static_assert boostorg/static_assert) +add_subdirectory(../../../throw_exception boostorg/throw_exception) add_executable(quick ../quick.cpp) target_link_libraries(quick Boost::core) From 493832a5701a30e3a8080dc1eaecefd749cd4ed2 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 27 Oct 2021 02:57:55 +0300 Subject: [PATCH 096/258] Remove string_view from documentation --- doc/changes.qbk | 3 --- doc/core.qbk | 1 - 2 files changed, 4 deletions(-) diff --git a/doc/changes.qbk b/doc/changes.qbk index 6f37292..5168026 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -11,9 +11,6 @@ * Added a generic implementation to `boost/core/cmath.hpp`, enabled when `BOOST_CORE_USE_GENERIC_CMATH` is defined or when the platform does not provide the necessary facilities in ``. * Added `boost::core::type_name`, a utility function that returns the name of a type as a string. -* Added `boost::core::string_view`, a portable implementation of C++17's `std::string_view` that differs - from `boost::string_view` by supporting implicit conversions from and to `std::string_view`, when that - is available. * Added `boost::span`, a C++11 implementation of C++20's `std::span`. [endsect] diff --git a/doc/core.qbk b/doc/core.qbk index 55101e3..7f7a75b 100644 --- a/doc/core.qbk +++ b/doc/core.qbk @@ -66,7 +66,6 @@ criteria for inclusion is that the utility component be: [include ref.qbk] [include scoped_enum.qbk] [include span.qbk] -[include string_view.qbk] [include swap.qbk] [include typeinfo.qbk] [include type_name.qbk] From 585ac9ace1a73f92ab76e1c72245667c0b24e49e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 27 Oct 2021 03:08:10 +0300 Subject: [PATCH 097/258] Move string_view.hpp to boost/core/detail --- include/boost/core/{ => detail}/string_view.hpp | 0 test/sv_compare_test.cpp | 2 +- test/sv_construct_test.cpp | 2 +- test/sv_contains_test.cpp | 2 +- test/sv_conversion_test.cpp | 2 +- test/sv_copy_test.cpp | 2 +- test/sv_element_access_test.cpp | 2 +- test/sv_ends_with_test.cpp | 2 +- test/sv_eq_test.cpp | 2 +- test/sv_find_first_not_of_test.cpp | 2 +- test/sv_find_first_of_test.cpp | 2 +- test/sv_find_last_not_of_test.cpp | 2 +- test/sv_find_last_of_test.cpp | 2 +- test/sv_find_test.cpp | 2 +- test/sv_iteration_test.cpp | 2 +- test/sv_lt_test.cpp | 2 +- test/sv_modifiers_test.cpp | 2 +- test/sv_rfind_test.cpp | 2 +- test/sv_starts_with_test.cpp | 2 +- test/sv_stream_insert_test.cpp | 2 +- test/sv_substr_test.cpp | 2 +- test/sv_types_test.cpp | 2 +- 22 files changed, 21 insertions(+), 21 deletions(-) rename include/boost/core/{ => detail}/string_view.hpp (100%) diff --git a/include/boost/core/string_view.hpp b/include/boost/core/detail/string_view.hpp similarity index 100% rename from include/boost/core/string_view.hpp rename to include/boost/core/detail/string_view.hpp diff --git a/test/sv_compare_test.cpp b/test/sv_compare_test.cpp index 26eba68..eef12d6 100644 --- a/test/sv_compare_test.cpp +++ b/test/sv_compare_test.cpp @@ -2,7 +2,7 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include #include #include #include diff --git a/test/sv_construct_test.cpp b/test/sv_construct_test.cpp index 0147828..3a33fbd 100644 --- a/test/sv_construct_test.cpp +++ b/test/sv_construct_test.cpp @@ -2,7 +2,7 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include #include #include #include diff --git a/test/sv_contains_test.cpp b/test/sv_contains_test.cpp index bb63491..f42f1e4 100644 --- a/test/sv_contains_test.cpp +++ b/test/sv_contains_test.cpp @@ -2,7 +2,7 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include #include #include diff --git a/test/sv_conversion_test.cpp b/test/sv_conversion_test.cpp index 604b1f9..64a7105 100644 --- a/test/sv_conversion_test.cpp +++ b/test/sv_conversion_test.cpp @@ -2,7 +2,7 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include #include #include #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) diff --git a/test/sv_copy_test.cpp b/test/sv_copy_test.cpp index 710718b..8dbd860 100644 --- a/test/sv_copy_test.cpp +++ b/test/sv_copy_test.cpp @@ -2,7 +2,7 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include #include #include #include diff --git a/test/sv_element_access_test.cpp b/test/sv_element_access_test.cpp index 12df69b..e4a94f7 100644 --- a/test/sv_element_access_test.cpp +++ b/test/sv_element_access_test.cpp @@ -2,7 +2,7 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include #include #include diff --git a/test/sv_ends_with_test.cpp b/test/sv_ends_with_test.cpp index 6c037ef..86de3da 100644 --- a/test/sv_ends_with_test.cpp +++ b/test/sv_ends_with_test.cpp @@ -2,7 +2,7 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include #include #include #include diff --git a/test/sv_eq_test.cpp b/test/sv_eq_test.cpp index ea48831..46e6ef7 100644 --- a/test/sv_eq_test.cpp +++ b/test/sv_eq_test.cpp @@ -2,7 +2,7 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include #include #include #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) diff --git a/test/sv_find_first_not_of_test.cpp b/test/sv_find_first_not_of_test.cpp index a32a6e1..92b12ed 100644 --- a/test/sv_find_first_not_of_test.cpp +++ b/test/sv_find_first_not_of_test.cpp @@ -2,7 +2,7 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include #include #include #include diff --git a/test/sv_find_first_of_test.cpp b/test/sv_find_first_of_test.cpp index f5704c0..e17ed6d 100644 --- a/test/sv_find_first_of_test.cpp +++ b/test/sv_find_first_of_test.cpp @@ -2,7 +2,7 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include #include #include #include diff --git a/test/sv_find_last_not_of_test.cpp b/test/sv_find_last_not_of_test.cpp index 96a71cd..0e7e974 100644 --- a/test/sv_find_last_not_of_test.cpp +++ b/test/sv_find_last_not_of_test.cpp @@ -2,7 +2,7 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include #include #include #include diff --git a/test/sv_find_last_of_test.cpp b/test/sv_find_last_of_test.cpp index 5cc0624..f058197 100644 --- a/test/sv_find_last_of_test.cpp +++ b/test/sv_find_last_of_test.cpp @@ -2,7 +2,7 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include #include #include #include diff --git a/test/sv_find_test.cpp b/test/sv_find_test.cpp index 537c975..cdf97ac 100644 --- a/test/sv_find_test.cpp +++ b/test/sv_find_test.cpp @@ -2,7 +2,7 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include #include #include diff --git a/test/sv_iteration_test.cpp b/test/sv_iteration_test.cpp index 7e85dc0..57078d6 100644 --- a/test/sv_iteration_test.cpp +++ b/test/sv_iteration_test.cpp @@ -2,7 +2,7 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include #include #include #include diff --git a/test/sv_lt_test.cpp b/test/sv_lt_test.cpp index 8c45150..dfa4227 100644 --- a/test/sv_lt_test.cpp +++ b/test/sv_lt_test.cpp @@ -2,7 +2,7 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include #include #include #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) diff --git a/test/sv_modifiers_test.cpp b/test/sv_modifiers_test.cpp index d292594..1a4d2b0 100644 --- a/test/sv_modifiers_test.cpp +++ b/test/sv_modifiers_test.cpp @@ -2,7 +2,7 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include #include #include diff --git a/test/sv_rfind_test.cpp b/test/sv_rfind_test.cpp index 65a0ee8..12ab0cc 100644 --- a/test/sv_rfind_test.cpp +++ b/test/sv_rfind_test.cpp @@ -2,7 +2,7 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include #include #include diff --git a/test/sv_starts_with_test.cpp b/test/sv_starts_with_test.cpp index e3d69c5..8fa8869 100644 --- a/test/sv_starts_with_test.cpp +++ b/test/sv_starts_with_test.cpp @@ -2,7 +2,7 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include #include #include #include diff --git a/test/sv_stream_insert_test.cpp b/test/sv_stream_insert_test.cpp index cebdf01..864c2bd 100644 --- a/test/sv_stream_insert_test.cpp +++ b/test/sv_stream_insert_test.cpp @@ -2,7 +2,7 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include #include #include #include diff --git a/test/sv_substr_test.cpp b/test/sv_substr_test.cpp index 666aebf..51cde0a 100644 --- a/test/sv_substr_test.cpp +++ b/test/sv_substr_test.cpp @@ -2,7 +2,7 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include #include #include #include diff --git a/test/sv_types_test.cpp b/test/sv_types_test.cpp index 9f2592a..9011f0c 100644 --- a/test/sv_types_test.cpp +++ b/test/sv_types_test.cpp @@ -2,7 +2,7 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include #include #include #include From 79b7c49fb32ab16205c5b79b0818ec71a1f1d9ef Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 27 Oct 2021 03:18:52 +0300 Subject: [PATCH 098/258] Refactor typeid_name slighlty --- include/boost/core/type_name.hpp | 56 +++++++++++++++++++------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/include/boost/core/type_name.hpp b/include/boost/core/type_name.hpp index 8a118ad..526d5d9 100644 --- a/include/boost/core/type_name.hpp +++ b/include/boost/core/type_name.hpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) # include @@ -41,54 +42,60 @@ template struct tn_identity typedef T type; }; +// tn_remove_prefix + +inline bool tn_remove_prefix( std::string& str, char const* prefix ) +{ + std::size_t n = std::strlen( prefix ); + + if( str.substr( 0, n ) == prefix ) + { + str = str.substr( n ); + return true; + } + else + { + return false; + } +} + #if !defined(BOOST_NO_TYPEID) // typeid_name -template std::string typeid_name() +inline std::string fix_typeid_name( char const* n ) { - std::string r = boost::core::demangle( typeid(T).name() ); + std::string r = boost::core::demangle( n ); #if defined(_MSC_VER) - if( r.substr( 0, 6 ) == "class " ) - { - r = r.substr( 6 ); - } - - if( r.substr( 0, 7 ) == "struct " ) - { - r = r.substr( 7 ); - } - - if( r.substr( 0, 5 ) == "enum " ) - { - r = r.substr( 5 ); - } + tn_remove_prefix( r, "class " ); + tn_remove_prefix( r, "struct " ); + tn_remove_prefix( r, "enum " ); #endif // libc++ inline namespace - if( r.substr( 0, 10 ) == "std::__1::" ) + if( tn_remove_prefix( r, "std::__1::" ) ) { - r = "std::" + r.substr( 10 ); + r = "std::" + r; } // libstdc++ inline namespace - if( r.substr( 0, 14 ) == "std::__cxx11::" ) + if( tn_remove_prefix( r, "std::__cxx11::" ) ) { - r = "std::" + r.substr( 14 ); + r = "std::" + r; } #if defined(BOOST_MSVC) && BOOST_MSVC == 1600 // msvc-10.0 puts TR1 things in std::tr1 - if( r.substr( 0, 10 ) == "std::tr1::" ) + if( tn_remove_prefix( r, "std::tr1::" ) ) { - r = "std::" + r.substr( 10 ); + r = "std::" + r; } #endif @@ -96,6 +103,11 @@ template std::string typeid_name() return r; } +template std::string typeid_name() +{ + return fix_typeid_name( typeid(T).name() ); +} + // template names template std::string class_template_name() From e9718374ac6d6c27de4dc90e630e2064d786ed3c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 27 Oct 2021 03:41:40 +0300 Subject: [PATCH 099/258] Hardcode all integral and floating point types --- include/boost/core/type_name.hpp | 140 ++++++++++++++++++++++++++++++- 1 file changed, 139 insertions(+), 1 deletion(-) diff --git a/include/boost/core/type_name.hpp b/include/boost/core/type_name.hpp index 526d5d9..853ca33 100644 --- a/include/boost/core/type_name.hpp +++ b/include/boost/core/type_name.hpp @@ -209,6 +209,62 @@ template struct tn_holder // integrals +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "bool" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "char" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "signed char" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "unsigned char" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "short" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "unsigned short" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "int" + suffix; + } +}; + template<> struct tn_holder { static std::string type_name( std::string const& suffix ) @@ -217,7 +273,21 @@ template<> struct tn_holder } }; -#if defined(_MSC_VER) +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "long" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "unsigned long" + suffix; + } +}; template<> struct tn_holder { @@ -235,6 +305,36 @@ template<> struct tn_holder } }; +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "wchar_t" + suffix; + } +}; + +#if !defined(BOOST_NO_CXX11_CHAR16_T) + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "char16_t" + suffix; + } +}; + +#endif + +#if !defined(BOOST_NO_CXX11_CHAR32_T) + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "char32_t" + suffix; + } +}; + #endif #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L @@ -249,6 +349,44 @@ template<> struct tn_holder #endif +#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "std::byte" + suffix; + } +}; + +#endif + +// floating point + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "float" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "double" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "long double" + suffix; + } +}; + // cv template struct tn_holder From fda0f875768476d40a788f6b280d7c30b345deb9 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 27 Oct 2021 03:46:06 +0300 Subject: [PATCH 100/258] Add void, move nullptr_t to fundamental type section --- include/boost/core/type_name.hpp | 38 ++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/include/boost/core/type_name.hpp b/include/boost/core/type_name.hpp index 853ca33..19ae1b5 100644 --- a/include/boost/core/type_name.hpp +++ b/include/boost/core/type_name.hpp @@ -387,6 +387,30 @@ template<> struct tn_holder } }; +// void + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "void" + suffix; + } +}; + +// nullptr_t + +#if !defined(BOOST_NO_CXX11_NULLPTR) + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "std::nullptr_t" + suffix; + } +}; + +#endif + // cv template struct tn_holder @@ -854,20 +878,6 @@ template struct tn_holder struct tn_holder -{ - static std::string type_name( std::string const& suffix ) - { - return "std::nullptr_t" + suffix; - } -}; - -#endif - // strings template class L, class Ch> struct tn_holder< L, std::allocator > > From 056545662231b8c77f1ca7d937f5d30133b53fc6 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 27 Oct 2021 04:45:40 +0300 Subject: [PATCH 101/258] Use boost::(u)long_long_type to avoid g++ warning --- include/boost/core/type_name.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/core/type_name.hpp b/include/boost/core/type_name.hpp index 19ae1b5..4afef1d 100644 --- a/include/boost/core/type_name.hpp +++ b/include/boost/core/type_name.hpp @@ -289,7 +289,7 @@ template<> struct tn_holder } }; -template<> struct tn_holder +template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { @@ -297,7 +297,7 @@ template<> struct tn_holder } }; -template<> struct tn_holder +template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { From 12f5f51427fbc9d27f56e5de002b0008fea420c9 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Wed, 27 Oct 2021 01:41:40 -0400 Subject: [PATCH 102/258] Switch tests to not rely on requires checks --- test/Jamfile.v2 | 13 ++++++------- test/as_bytes_test.cpp | 8 ++++++++ test/as_writable_bytes_test.cpp | 8 ++++++++ test/span_constructible_test.cpp | 8 ++++++++ test/span_deduction_guide_test.cpp | 7 +++++++ test/span_test.cpp | 8 ++++++++ test/span_types_test.cpp | 8 ++++++++ 7 files changed, 53 insertions(+), 7 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index f645a07..4033219 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -8,7 +8,6 @@ import modules ; import testing ; -import ../../config/checks/config : requires ; # quick test (for CI) run quick.cpp ; @@ -270,12 +269,12 @@ run sv_lt_test.cpp ; run sv_stream_insert_test.cpp ; run sv_conversion_test.cpp ; -run span_test.cpp : : : [ requires cxx11_constexpr cxx11_decltype ] ; -run span_types_test.cpp : : : [ requires cxx11_constexpr cxx11_decltype ] ; -run span_constructible_test.cpp : : : [ requires cxx11_constexpr cxx11_decltype ] ; -run span_deduction_guide_test.cpp : : : [ requires cpp_deduction_guides ] ; -run as_bytes_test.cpp : : : [ requires cpp_lib_byte ] ; -run as_writable_bytes_test.cpp : : : [ requires cpp_lib_byte ] ; +run span_test.cpp ; +run span_types_test.cpp ; +run span_constructible_test.cpp ; +run span_deduction_guide_test.cpp ; +run as_bytes_test.cpp ; +run as_writable_bytes_test.cpp ; use-project /boost/core/swap : ./swap ; build-project ./swap ; diff --git a/test/as_bytes_test.cpp b/test/as_bytes_test.cpp index e99ef5d..2c714aa 100644 --- a/test/as_bytes_test.cpp +++ b/test/as_bytes_test.cpp @@ -5,6 +5,8 @@ Copyright 2019 Glen Joseph Fernandes Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ +#include +#ifdef __cpp_lib_byte #include #include @@ -32,3 +34,9 @@ int main() test_static(); return boost::report_errors(); } +#else +int main() +{ + return 0; +} +#endif diff --git a/test/as_writable_bytes_test.cpp b/test/as_writable_bytes_test.cpp index 47914d8..8ef59be 100644 --- a/test/as_writable_bytes_test.cpp +++ b/test/as_writable_bytes_test.cpp @@ -5,6 +5,8 @@ Copyright 2019 Glen Joseph Fernandes Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ +#include +#ifdef __cpp_lib_byte #include #include @@ -32,3 +34,9 @@ int main() test_static(); return boost::report_errors(); } +#else +int main() +{ + return 0; +} +#endif diff --git a/test/span_constructible_test.cpp b/test/span_constructible_test.cpp index 857eada..01e4542 100644 --- a/test/span_constructible_test.cpp +++ b/test/span_constructible_test.cpp @@ -5,6 +5,8 @@ Copyright 2019 Glen Joseph Fernandes Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ +#include +#if !defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CXX11_DECLTYPE) #include #include @@ -190,3 +192,9 @@ int main() test_assign(); return boost::report_errors(); } +#else +int main() +{ + return 0; +} +#endif diff --git a/test/span_deduction_guide_test.cpp b/test/span_deduction_guide_test.cpp index c627ba8..519c881 100644 --- a/test/span_deduction_guide_test.cpp +++ b/test/span_deduction_guide_test.cpp @@ -5,6 +5,7 @@ Copyright 2019 Glen Joseph Fernandes Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ +#ifdef __cpp_deduction_guides #include #include @@ -107,3 +108,9 @@ int main() test_span_static(); return boost::report_errors(); } +#else +int main() +{ + return 0; +} +#endif diff --git a/test/span_test.cpp b/test/span_test.cpp index 5ef1d22..1009cba 100644 --- a/test/span_test.cpp +++ b/test/span_test.cpp @@ -5,6 +5,8 @@ Copyright 2019 Glen Joseph Fernandes Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ +#include +#if !defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CXX11_DECLTYPE) #include #include @@ -423,3 +425,9 @@ int main() test_end_span(); return boost::report_errors(); } +#else +int main() +{ + return 0; +} +#endif diff --git a/test/span_types_test.cpp b/test/span_types_test.cpp index 56c7413..49f7346 100644 --- a/test/span_types_test.cpp +++ b/test/span_types_test.cpp @@ -5,6 +5,8 @@ Copyright 2019 Glen Joseph Fernandes Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ +#include +#if !defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CXX11_DECLTYPE) #include #include @@ -126,3 +128,9 @@ int main() test_const_reverse_iterator(); return boost::report_errors(); } +#else +int main() +{ + return 0; +} +#endif From 9d1b59ec6c4c3a8e1402394d757cb1c4fd29f8ef Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 01:24:02 +0200 Subject: [PATCH 103/258] Enable warnings=extra, warnings-as-errors=on --- test/Jamfile.v2 | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 4033219..42fea1f 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -9,6 +9,13 @@ import modules ; import testing ; +project : requirements + + extra + msvc:on + clang:on + gcc:on ; + # quick test (for CI) run quick.cpp ; From 309a6bb797ac85a08a0b1a6654af8d018091c024 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 01:27:01 +0200 Subject: [PATCH 104/258] Fix unused parameter 't' warnings in eif_*.cpp --- test/eif_dummy_arg_disambiguation.cpp | 5 ++--- test/eif_lazy_test.cpp | 9 ++++----- test/eif_namespace_disambiguation.cpp | 5 ++--- test/eif_no_disambiguation.cpp | 5 ++--- 4 files changed, 10 insertions(+), 14 deletions(-) diff --git a/test/eif_dummy_arg_disambiguation.cpp b/test/eif_dummy_arg_disambiguation.cpp index ab65f4f..78346c0 100644 --- a/test/eif_dummy_arg_disambiguation.cpp +++ b/test/eif_dummy_arg_disambiguation.cpp @@ -24,11 +24,11 @@ template struct dummy { template typename enable_if, bool>::type -arithmetic_object(T t, dummy<0> = 0) { return true; } +arithmetic_object(T /*t*/, dummy<0> = 0) { return true; } template typename disable_if, bool>::type -arithmetic_object(T t, dummy<1> = 0) { return false; } +arithmetic_object(T /*t*/, dummy<1> = 0) { return false; } int main() @@ -42,4 +42,3 @@ int main() return boost::report_errors(); } - diff --git a/test/eif_lazy_test.cpp b/test/eif_lazy_test.cpp index 905d0a9..8938a3d 100644 --- a/test/eif_lazy_test.cpp +++ b/test/eif_lazy_test.cpp @@ -60,21 +60,21 @@ namespace A { template typename lazy_enable_if, some_traits >::type - foo(T t) { return true; } + foo(T /*t*/) { return true; } template typename lazy_enable_if_c::value, some_traits >::type - foo2(T t) { return true; } + foo2(T /*t*/) { return true; } } namespace B { template typename lazy_disable_if, make_bool >::type - foo(T t) { return false; } + foo(T /*t*/) { return false; } template typename lazy_disable_if_c::value, make_bool >::type - foo2(T t) { return false; } + foo2(T /*t*/) { return false; } } int main() @@ -95,4 +95,3 @@ int main() return boost::report_errors(); } - diff --git a/test/eif_namespace_disambiguation.cpp b/test/eif_namespace_disambiguation.cpp index d5589ae..fd24a4b 100644 --- a/test/eif_namespace_disambiguation.cpp +++ b/test/eif_namespace_disambiguation.cpp @@ -26,13 +26,13 @@ template struct not_ namespace A { template typename enable_if, bool>::type - arithmetic_object(T t) { return true; } + arithmetic_object(T /*t*/) { return true; } } namespace B { template typename enable_if >, bool>::type - arithmetic_object(T t) { return false; } + arithmetic_object(T /*t*/) { return false; } } int main() @@ -47,4 +47,3 @@ int main() return boost::report_errors(); } - diff --git a/test/eif_no_disambiguation.cpp b/test/eif_no_disambiguation.cpp index 3853cbf..37afb43 100644 --- a/test/eif_no_disambiguation.cpp +++ b/test/eif_no_disambiguation.cpp @@ -25,11 +25,11 @@ template struct not_ template typename enable_if, bool>::type -arithmetic_object(T t) { return true; } +arithmetic_object(T /*t*/) { return true; } template typename enable_if >, bool>::type -arithmetic_object(T t) { return false; } +arithmetic_object(T /*t*/) { return false; } int main() @@ -43,4 +43,3 @@ int main() return boost::report_errors(); } - From 9b5bf05faeea45e05017dc25ee1af03289a1a2f6 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 01:29:15 +0200 Subject: [PATCH 105/258] Disable -Wdeprecated-declarations in get_pointer_test.cpp --- test/get_pointer_test.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/get_pointer_test.cpp b/test/get_pointer_test.cpp index 1ddf3be..4bccccb 100644 --- a/test/get_pointer_test.cpp +++ b/test/get_pointer_test.cpp @@ -8,6 +8,10 @@ // http://www.boost.org/LICENSE_1_0.txt // +#if defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" // std::auto_ptr +#endif + #include #include #include From bb99544852e93b0cd510efe47a4c5b3e06dac301 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 01:35:57 +0200 Subject: [PATCH 106/258] Use warnings-as-errors=off for compile-fail tests --- test/Jamfile.v2 | 68 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 42fea1f..bdcc8f7 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -16,6 +16,11 @@ project : requirements clang:on gcc:on ; +local warning-as-errors-off = + "-msvc:on" + "-gcc:on" + "-clang:on" ; + # quick test (for CI) run quick.cpp ; @@ -25,25 +30,37 @@ run addressof_test2.cpp ; run addressof_np_test.cpp ; run addressof_fn_test.cpp ; compile addressof_constexpr_test.cpp ; -compile-fail addressof_fail_rvalue.cpp ; +compile-fail addressof_fail_rvalue.cpp + : $(warning-as-errors-off) ; run checked_delete_test.cpp ; -compile-fail checked_delete_fail.cpp ; -compile-fail checked_delete_fail2.cpp ; +compile-fail checked_delete_fail.cpp + : $(warning-as-errors-off) ; +compile-fail checked_delete_fail2.cpp + : $(warning-as-errors-off) ; compile ref_ct_test.cpp ; run ref_test.cpp ; run ref_ref_test.cpp ; run ref_fn_test.cpp ; -compile-fail ref_rv_fail1.cpp ; -compile-fail ref_rv_fail2.cpp ; -compile-fail ref_rv_fail3.cpp ; -compile-fail ref_rv_fail4.cpp ; -compile-fail ref_rv_fail5.cpp ; -compile-fail ref_implicit_fail.cpp ; -compile-fail ref_implicit_fail2.cpp ; -compile-fail ref_implicit_fail3.cpp ; -compile-fail ref_implicit_fail4.cpp ; +compile-fail ref_rv_fail1.cpp + : $(warning-as-errors-off) ; +compile-fail ref_rv_fail2.cpp + : $(warning-as-errors-off) ; +compile-fail ref_rv_fail3.cpp + : $(warning-as-errors-off) ; +compile-fail ref_rv_fail4.cpp + : $(warning-as-errors-off) ; +compile-fail ref_rv_fail5.cpp + : $(warning-as-errors-off) ; +compile-fail ref_implicit_fail.cpp + : $(warning-as-errors-off) ; +compile-fail ref_implicit_fail2.cpp + : $(warning-as-errors-off) ; +compile-fail ref_implicit_fail3.cpp + : $(warning-as-errors-off) ; +compile-fail ref_implicit_fail4.cpp + : $(warning-as-errors-off) ; run ref_cv_test.cpp ; run ref_conversion_test.cpp ; @@ -56,20 +73,21 @@ run eif_namespace_disambiguation.cpp : ; run eif_no_disambiguation.cpp : ; run eif_partial_specializations.cpp : ; -compile-fail noncopyable_compile_fail.cpp ; +compile-fail noncopyable_compile_fail.cpp + : $(warning-as-errors-off) ; run explicit_operator_bool.cpp ; run explicit_operator_bool_noexcept.cpp ; -compile-fail explicit_operator_bool_compile_fail_conv_int.cpp ; -compile-fail explicit_operator_bool_compile_fail_conv_pvoid.cpp ; -compile-fail explicit_operator_bool_compile_fail_delete.cpp ; -compile-fail explicit_operator_bool_compile_fail_shift.cpp ; +compile-fail explicit_operator_bool_compile_fail_conv_int.cpp + : $(warning-as-errors-off) ; +compile-fail explicit_operator_bool_compile_fail_conv_pvoid.cpp + : $(warning-as-errors-off) ; +compile-fail explicit_operator_bool_compile_fail_delete.cpp + : $(warning-as-errors-off) ; +compile-fail explicit_operator_bool_compile_fail_shift.cpp + : $(warning-as-errors-off) ; -compile ignore_unused_test.cpp - : extra - gcc:on - clang:on - msvc:on ; +compile ignore_unused_test.cpp ; run sp_typeinfo_test.cpp ; run sp_typeinfo_test.cpp : : : off : sp_typeinfo_test_no_rtti ; @@ -158,8 +176,10 @@ run demangled_name_test.cpp run demangled_name_test.cpp : : : off always_show_run_output : demangled_name_test_no_rtti ; run scoped_enum.cpp ; -compile-fail scoped_enum_compile_fail_conv_from_int.cpp ; -compile-fail scoped_enum_compile_fail_conv_to_int.cpp ; +compile-fail scoped_enum_compile_fail_conv_from_int.cpp + : $(warning-as-errors-off) ; +compile-fail scoped_enum_compile_fail_conv_to_int.cpp + : $(warning-as-errors-off) ; run underlying_type.cpp ; From 62d1b1bb59ccf666a18366fc86fd45c1484f1fbd Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 01:39:13 +0200 Subject: [PATCH 107/258] Avoid sturct/class mismatch warning in use_default_test.cpp --- test/use_default_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/use_default_test.cpp b/test/use_default_test.cpp index adf1da6..69e6e68 100644 --- a/test/use_default_test.cpp +++ b/test/use_default_test.cpp @@ -11,5 +11,5 @@ Distributed under the Boost Software License, Version 1.0. template struct type { }; -template class type; -template class type; +template struct type; +template struct type; From 370a74c2493c0eca39fb4385e975e1259b7edf0d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 01:41:54 +0200 Subject: [PATCH 108/258] Avoid self-assignment warning in ref_ct_test.cpp --- test/ref_ct_test.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/ref_ct_test.cpp b/test/ref_ct_test.cpp index 7e97957..9e5bf31 100644 --- a/test/ref_ct_test.cpp +++ b/test/ref_ct_test.cpp @@ -21,10 +21,16 @@ void ref_test(boost::reference_wrapper) BOOST_STATIC_ASSERT((boost::core::is_same::value)); } +template< typename T > +void assignable_test_(T x1, T x2) +{ + x1 = x2; +} + template< typename T > void assignable_test(T x) { - x = x; + assignable_test_( x, x ); } template< bool R, typename T > From d81c61abb4a1f95fce1029d9edbe52e6d994d072 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 01:43:50 +0200 Subject: [PATCH 109/258] Disable -Wstring-plus-int in lightweight_test_fail10.cpp --- test/lightweight_test_fail10.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/lightweight_test_fail10.cpp b/test/lightweight_test_fail10.cpp index 388c47e..80cd49d 100644 --- a/test/lightweight_test_fail10.cpp +++ b/test/lightweight_test_fail10.cpp @@ -8,6 +8,10 @@ // http://www.boost.org/LICENSE_1_0.txt // +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wstring-plus-int" +#endif + #include int main() From 971cda2e4c5695a80363de841b9294b06fdbe4d2 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 01:45:15 +0200 Subject: [PATCH 110/258] Avoid -Wmissing-braces in swap_array_of_template.cpp --- test/swap/swap_array_of_template.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/swap/swap_array_of_template.cpp b/test/swap/swap_array_of_template.cpp index c0e76e3..1ec33fd 100644 --- a/test/swap/swap_array_of_template.cpp +++ b/test/swap/swap_array_of_template.cpp @@ -50,8 +50,8 @@ void swap(swap_test_template& left, swap_test_template& right) int main() { const std::size_t array_size = 2; - const swap_test_template initial_array1[array_size] = { swap_test_class(1), swap_test_class(2) }; - const swap_test_template initial_array2[array_size] = { swap_test_class(3), swap_test_class(4) }; + const swap_test_template initial_array1[array_size] = { { swap_test_class(1) }, { swap_test_class(2) } }; + const swap_test_template initial_array2[array_size] = { { swap_test_class(3) }, { swap_test_class(4) } }; swap_test_template array1[array_size]; swap_test_template array2[array_size]; From bed07e7d5b236aefc23ddd3eb6721dfd09dcba2b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 01:47:28 +0200 Subject: [PATCH 111/258] Disable -Wdeprecated-declarations in iterator_test.cpp --- test/iterator_test.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/iterator_test.cpp b/test/iterator_test.cpp index 3eb2902..7388cbe 100644 --- a/test/iterator_test.cpp +++ b/test/iterator_test.cpp @@ -8,6 +8,10 @@ // http://www.boost.org/LICENSE_1_0.txt // +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wdeprecated-declarations" +#endif + #include #include #include From b5f59858b945b97f276dfbd7557d4337e051dd75 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 01:56:27 +0200 Subject: [PATCH 112/258] Avoid unused parameter warning in visit_each_test.cpp --- test/visit_each_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/visit_each_test.cpp b/test/visit_each_test.cpp index 726188e..a0da6be 100644 --- a/test/visit_each_test.cpp +++ b/test/visit_each_test.cpp @@ -34,7 +34,7 @@ struct V { } - template< class T > void operator()( T const & t ) + template< class T > void operator()( T const & /*t*/ ) { } From 44e294fff12b993bc514bf0825cc8ea5dcc9a162 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 01:58:05 +0200 Subject: [PATCH 113/258] Avoid unused parameter warning in to_address_test.cpp --- test/to_address_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/to_address_test.cpp b/test/to_address_test.cpp index e1b55c4..4c02384 100644 --- a/test/to_address_test.cpp +++ b/test/to_address_test.cpp @@ -124,7 +124,7 @@ struct pointer_traits > { namespace std { template struct pointer_traits > { - static T* to_address(const P6& p) BOOST_NOEXCEPT { + static T* to_address(const P6& /*p*/) BOOST_NOEXCEPT { return 0; } }; From 847f9d43febc59d801b47c0d55ddde1d0ce8363b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 02:04:45 +0200 Subject: [PATCH 114/258] Disable C4702 in quick_exit_test.cpp, quick_exit_fail.cpp --- test/quick_exit_fail.cpp | 4 +++- test/quick_exit_test.cpp | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/test/quick_exit_fail.cpp b/test/quick_exit_fail.cpp index b1d394e..e32c298 100644 --- a/test/quick_exit_fail.cpp +++ b/test/quick_exit_fail.cpp @@ -1,4 +1,3 @@ - // Test for quick_exit.hpp // // Copyright 2018 Peter Dimov @@ -7,6 +6,9 @@ // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt +#if defined(_MSC_VER) +# pragma warning(disable: 4702) // unreachable code +#endif #include diff --git a/test/quick_exit_test.cpp b/test/quick_exit_test.cpp index e5f7795..9b25ac5 100644 --- a/test/quick_exit_test.cpp +++ b/test/quick_exit_test.cpp @@ -1,4 +1,3 @@ - // Test for quick_exit.hpp // // Copyright 2018 Peter Dimov @@ -7,6 +6,9 @@ // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt +#if defined(_MSC_VER) +# pragma warning(disable: 4702) // unreachable code +#endif #include From 8299d25eb224c87260301b701dbb736390dbadd2 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 02:06:42 +0200 Subject: [PATCH 115/258] Avoid size_t to int conversion warning in visit_each_test.cpp --- test/visit_each_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/visit_each_test.cpp b/test/visit_each_test.cpp index a0da6be..d1fcc3c 100644 --- a/test/visit_each_test.cpp +++ b/test/visit_each_test.cpp @@ -45,7 +45,7 @@ struct V void operator()( std::string const & w ) { - s_ = s_ * 10 + w.size(); + s_ = s_ * 10 + static_cast( w.size() ); } }; From a4b661068d073f68969f237e199de3fe7451630b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 02:14:43 +0200 Subject: [PATCH 116/258] Disable C4127, C4244 in bit.hpp --- include/boost/core/bit.hpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/boost/core/bit.hpp b/include/boost/core/bit.hpp index c469bc8..f4305b9 100644 --- a/include/boost/core/bit.hpp +++ b/include/boost/core/bit.hpp @@ -22,13 +22,20 @@ #include #if defined(_MSC_VER) + # include # pragma intrinsic(_BitScanForward) # pragma intrinsic(_BitScanReverse) + # if defined(_M_X64) # pragma intrinsic(_BitScanForward64) # pragma intrinsic(_BitScanReverse64) # endif + +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +# pragma warning(disable: 4244) // conversion from int to T + #endif // defined(_MSC_VER) namespace boost @@ -578,4 +585,8 @@ typedef endian::type endian_type; } // namespace core } // namespace boost +#if defined(_MSC_VER) +# pragma warning(pop) +#endif + #endif // #ifndef BOOST_CORE_BIT_HPP_INCLUDED From bf4354a3a4891f7626a888c08945a003f5ed1fee Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 02:16:31 +0200 Subject: [PATCH 117/258] Disable C4127 in bit_endian_test.cpp --- test/bit_endian_test.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/bit_endian_test.cpp b/test/bit_endian_test.cpp index 361df16..b682e1b 100644 --- a/test/bit_endian_test.cpp +++ b/test/bit_endian_test.cpp @@ -9,6 +9,10 @@ #include #include +#if defined(_MSC_VER) +# pragma warning(disable: 4127) // conditional expression is constant +#endif + int main() { boost::uint64_t v = static_cast( 0x0102030405060708ull ); From bbfa6344faaf3caafcfb7f4819f492cf8929c590 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 02:18:51 +0200 Subject: [PATCH 118/258] Avoid ptrdiff_t -> int warning in eif_constructors.cpp --- test/eif_constructors.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/eif_constructors.cpp b/test/eif_constructors.cpp index 6314c85..0cd3a97 100644 --- a/test/eif_constructors.cpp +++ b/test/eif_constructors.cpp @@ -13,6 +13,7 @@ #include #include #include +#include using boost::enable_if; using boost::disable_if; @@ -39,7 +40,7 @@ struct xstring disable_if >::type* = 0) : data(end-begin) {} - int data; + std::ptrdiff_t data; }; @@ -58,4 +59,3 @@ int main() return boost::report_errors(); } - From ba208ad7fc968756b025400881c441e1bb988bb3 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 02:20:26 +0200 Subject: [PATCH 119/258] Avoid signed/unsigned mismatch warning in span.hpp --- include/boost/core/span.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/core/span.hpp b/include/boost/core/span.hpp index bafb286..39f5cef 100644 --- a/include/boost/core/span.hpp +++ b/include/boost/core/span.hpp @@ -15,7 +15,7 @@ Distributed under the Boost Software License, Version 1.0. namespace boost { -constexpr std::size_t dynamic_extent = -1; +constexpr std::size_t dynamic_extent = static_cast( -1 ); template class span; From da3c89dc5b8198f433d07a6519ab01580644a44f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 02:26:06 +0200 Subject: [PATCH 120/258] Apply a better fix to iterator_test.cpp --- test/iterator_test.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/iterator_test.cpp b/test/iterator_test.cpp index 7388cbe..c0e64a3 100644 --- a/test/iterator_test.cpp +++ b/test/iterator_test.cpp @@ -8,9 +8,7 @@ // http://www.boost.org/LICENSE_1_0.txt // -#if defined(__clang__) -# pragma clang diagnostic ignored "-Wdeprecated-declarations" -#endif +#define _SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING #include #include From 9efeed68cb65988d240e39796e0cb34619f11bf4 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 02:32:49 +0200 Subject: [PATCH 121/258] Disable C4530 in no_exceptions_support_test.cpp --- test/no_exceptions_support_test.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/no_exceptions_support_test.cpp b/test/no_exceptions_support_test.cpp index 64533fa..e5dc9ac 100644 --- a/test/no_exceptions_support_test.cpp +++ b/test/no_exceptions_support_test.cpp @@ -8,6 +8,10 @@ // http://www.boost.org/LICENSE_1_0.txt // +#if defined(_MSC_VER) +# pragma warning(disable: 4530) // C++ exception handler used +#endif + #include #include #include From 56566d9abc1f6422b33957a55cfbab93c5c4037e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 02:38:19 +0200 Subject: [PATCH 122/258] Disable C4100 in alloc_construct_cxx11_test.cpp --- test/alloc_construct_cxx11_test.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/alloc_construct_cxx11_test.cpp b/test/alloc_construct_cxx11_test.cpp index 2075d7a..928cec8 100644 --- a/test/alloc_construct_cxx11_test.cpp +++ b/test/alloc_construct_cxx11_test.cpp @@ -10,6 +10,10 @@ Distributed under the Boost Software License, Version 1.0. #include #include +#if defined(_MSC_VER) +# pragma warning(disable: 4100) // unreferenced parameter 'ptr' +#endif + class type { public: explicit type(int x) From 11958e956868cd1b7c400da22fdcb3ca3145b636 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 02:42:03 +0200 Subject: [PATCH 123/258] Avoid C4101 in scoped_enum.cpp --- test/scoped_enum.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/scoped_enum.cpp b/test/scoped_enum.cpp index 2a83749..3d9afa1 100644 --- a/test/scoped_enum.cpp +++ b/test/scoped_enum.cpp @@ -142,6 +142,7 @@ void check_underlying_type() // The real check for the type is in the underlying_type trait test. namespace_enum2 enum1 = namespace_enum2::value1; BOOST_TEST(sizeof(enum1) == sizeof(unsigned char)); + (void)enum1; } int main(int, char*[]) From e44781e2909071a34b5846fd3ad63c74cf20e03d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 02:43:48 +0200 Subject: [PATCH 124/258] Avoid C4101 in explicit_operator_bool_noexcept.cpp --- test/explicit_operator_bool_noexcept.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/explicit_operator_bool_noexcept.cpp b/test/explicit_operator_bool_noexcept.cpp index d4b69eb..e913043 100644 --- a/test/explicit_operator_bool_noexcept.cpp +++ b/test/explicit_operator_bool_noexcept.cpp @@ -76,6 +76,11 @@ int main(int, char*[]) BOOST_TEST(noexcept(static_cast< bool >(noexcept_val1))); BOOST_TEST(noexcept(static_cast< bool >(noexcept_val2))); + (void)val1; + (void)val2; + (void)noexcept_val1; + (void)noexcept_val2; + return boost::report_errors(); } From a581a42c4facbd664dc57abdfd04c5ace01b21dd Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 02:50:16 +0200 Subject: [PATCH 125/258] Disable C4577 in no_exceptions_support_test.cpp --- test/no_exceptions_support_test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/no_exceptions_support_test.cpp b/test/no_exceptions_support_test.cpp index e5dc9ac..7e227b9 100644 --- a/test/no_exceptions_support_test.cpp +++ b/test/no_exceptions_support_test.cpp @@ -10,6 +10,7 @@ #if defined(_MSC_VER) # pragma warning(disable: 4530) // C++ exception handler used +# pragma warning(disable: 4577) // noexcept used without /EHsc #endif #include From eae98e909e874e978f282ec5e93ddb0e760636ca Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Sun, 31 Oct 2021 20:50:02 -0400 Subject: [PATCH 126/258] MSVC warning workaround for as_bytes --- include/boost/core/span.hpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/boost/core/span.hpp b/include/boost/core/span.hpp index bafb286..a0be177 100644 --- a/include/boost/core/span.hpp +++ b/include/boost/core/span.hpp @@ -146,8 +146,12 @@ struct span_store { template struct span_bytes { - static constexpr std::size_t value = E == boost::dynamic_extent ? - boost::dynamic_extent : sizeof(T) * E; + static constexpr std::size_t value = sizeof(T) * E; +}; + +template +struct span_bytes { + static constexpr std::size_t value = boost::dynamic_extent; }; } /* detail */ From 633a47f85b56465de2a6a325cffcc29cb1f4fadc Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Sun, 31 Oct 2021 20:50:34 -0400 Subject: [PATCH 127/258] MSVC warning workaround for destroy --- include/boost/core/noinit_adaptor.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/core/noinit_adaptor.hpp b/include/boost/core/noinit_adaptor.hpp index 13ce4c8..962b6e4 100644 --- a/include/boost/core/noinit_adaptor.hpp +++ b/include/boost/core/noinit_adaptor.hpp @@ -56,6 +56,7 @@ struct noinit_adaptor template void destroy(U* p) { p->~U(); + (void)p; } }; From e73e8bfc83b2daed311167e7ceecb2d797b7a0c8 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 02:55:52 +0200 Subject: [PATCH 128/258] Disable C4512 in uncaught_exceptions(_np).cpp --- test/uncaught_exceptions.cpp | 4 ++++ test/uncaught_exceptions_np.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/test/uncaught_exceptions.cpp b/test/uncaught_exceptions.cpp index d8b1fc6..c5d7958 100644 --- a/test/uncaught_exceptions.cpp +++ b/test/uncaught_exceptions.cpp @@ -18,6 +18,10 @@ #include #include +#if defined(_MSC_VER) +# pragma warning(disable: 4512) // assignment operator could not be generated +#endif + struct my_exception {}; class exception_watcher diff --git a/test/uncaught_exceptions_np.cpp b/test/uncaught_exceptions_np.cpp index 7498ccf..f60aef1 100644 --- a/test/uncaught_exceptions_np.cpp +++ b/test/uncaught_exceptions_np.cpp @@ -20,6 +20,10 @@ #include +#if defined(_MSC_VER) +# pragma warning(disable: 4512) // assignment operator could not be generated +#endif + struct my_exception1 {}; struct my_exception2 {}; From 6a91536da60d982b9a6466560195b61eaeebbaa2 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 03:05:47 +0200 Subject: [PATCH 129/258] Disable -Wunused-function in swap_array(_of_array)_of_class.cpp --- test/swap/swap_array_of_array_of_class.cpp | 4 ++++ test/swap/swap_array_of_class.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/test/swap/swap_array_of_array_of_class.cpp b/test/swap/swap_array_of_array_of_class.cpp index 67541d3..1ea78da 100644 --- a/test/swap/swap_array_of_array_of_class.cpp +++ b/test/swap/swap_array_of_array_of_class.cpp @@ -17,6 +17,10 @@ #include //for std::copy and std::equal #include //for std::size_t +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wunused-function" +#endif + //Provide swap function in both the namespace of swap_test_class //(which is the global namespace), and the std namespace. //It's common to provide a swap function for a class in both diff --git a/test/swap/swap_array_of_class.cpp b/test/swap/swap_array_of_class.cpp index ef7327e..245602d 100644 --- a/test/swap/swap_array_of_class.cpp +++ b/test/swap/swap_array_of_class.cpp @@ -17,6 +17,10 @@ #include //for std::copy and std::equal #include //for std::size_t +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wunused-function" +#endif + //Provide swap function in both the namespace of swap_test_class //(which is the global namespace), and the std namespace. //It's common to provide a swap function for a class in both From 66f6ea594a0bfc42b9d7821613ca074b5ee1d960 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 03:10:42 +0200 Subject: [PATCH 130/258] Disable -Wtype-limits in string_view.hpp --- include/boost/core/detail/string_view.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/boost/core/detail/string_view.hpp b/include/boost/core/detail/string_view.hpp index 3c35c48..daa9a5d 100644 --- a/include/boost/core/detail/string_view.hpp +++ b/include/boost/core/detail/string_view.hpp @@ -49,6 +49,11 @@ template<> struct sv_to_uchar typedef unsigned char type; }; +#if defined(__GNUC__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wtype-limits" +#endif + template BOOST_CXX14_CONSTEXPR std::size_t find_first_of( Ch const* p_, std::size_t n_, Ch const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT { typedef typename sv_to_uchar::type UCh; @@ -315,6 +320,10 @@ template BOOST_CXX14_CONSTEXPR std::size_t find_last_not_of( Ch const* return npos; } +#if defined(__GNUC__) +# pragma GCC diagnostic pop +#endif + } // namespace detail template class basic_string_view From d2e897fd6026d816e8a0110b4a396fc807628a77 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Sun, 31 Oct 2021 21:14:40 -0400 Subject: [PATCH 131/258] MSVC warning workaround for dynamic_extent --- include/boost/core/span.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/core/span.hpp b/include/boost/core/span.hpp index a0be177..54dafdb 100644 --- a/include/boost/core/span.hpp +++ b/include/boost/core/span.hpp @@ -15,7 +15,7 @@ Distributed under the Boost Software License, Version 1.0. namespace boost { -constexpr std::size_t dynamic_extent = -1; +constexpr std::size_t dynamic_extent = static_cast(-1); template class span; From f09ab9024333cd2bf690b4c8096be14af56a3f1e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 03:14:53 +0200 Subject: [PATCH 132/258] Disable -Wsign-compare for g++ 4.4 --- test/Jamfile.v2 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index bdcc8f7..510db53 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -14,7 +14,8 @@ project : requirements extra msvc:on clang:on - gcc:on ; + gcc:on + gcc-4.4:-Wno-sign-compare ; local warning-as-errors-off = "-msvc:on" From 964ef98eee1e8b5d9fb01c2c8637fe52723aec54 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 03:52:09 +0200 Subject: [PATCH 133/258] Avoid streamsize -> size_t warning in string_view.hpp --- include/boost/core/detail/string_view.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/core/detail/string_view.hpp b/include/boost/core/detail/string_view.hpp index daa9a5d..3181d43 100644 --- a/include/boost/core/detail/string_view.hpp +++ b/include/boost/core/detail/string_view.hpp @@ -1151,9 +1151,9 @@ public: template std::basic_ostream& operator<<( std::basic_ostream& os, basic_string_view str ) { Ch const* p = str.data(); - std::size_t n = str.size(); + std::streamsize n = str.size(); - std::size_t m = os.width(); + std::streamsize m = os.width(); if( n >= m ) { From 9f2cdfa7d22825c9ee424f28c53367c8dff4d755 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 03:58:37 +0200 Subject: [PATCH 134/258] Disable C4244 in scoped_enum.cpp, underlying_type.cpp --- test/scoped_enum.cpp | 4 ++++ test/underlying_type.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/test/scoped_enum.cpp b/test/scoped_enum.cpp index 3d9afa1..3befebe 100644 --- a/test/scoped_enum.cpp +++ b/test/scoped_enum.cpp @@ -15,6 +15,10 @@ #include #include +#if defined(_MSC_VER) +# pragma warning(disable: 4244) // conversion from enum_type to underlying_type +#endif + BOOST_SCOPED_ENUM_DECLARE_BEGIN(namespace_enum1) { value0, diff --git a/test/underlying_type.cpp b/test/underlying_type.cpp index 0823f58..34f3940 100644 --- a/test/underlying_type.cpp +++ b/test/underlying_type.cpp @@ -18,6 +18,10 @@ #include #include +#if defined(_MSC_VER) +# pragma warning(disable: 4244) // conversion from enum_type to underlying_type +#endif + BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(emulated_enum, unsigned char) { value0, From bdd4bf7d9abc0158fae7c7813d594fa6b386bc23 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 04:04:52 +0200 Subject: [PATCH 135/258] #pragma GCC diagnostic push requires g++ 4.6 --- include/boost/core/detail/string_view.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/core/detail/string_view.hpp b/include/boost/core/detail/string_view.hpp index 3181d43..8b13c0f 100644 --- a/include/boost/core/detail/string_view.hpp +++ b/include/boost/core/detail/string_view.hpp @@ -49,7 +49,7 @@ template<> struct sv_to_uchar typedef unsigned char type; }; -#if defined(__GNUC__) +#if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 406 # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wtype-limits" #endif @@ -320,7 +320,7 @@ template BOOST_CXX14_CONSTEXPR std::size_t find_last_not_of( Ch const* return npos; } -#if defined(__GNUC__) +#if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 406 # pragma GCC diagnostic pop #endif From 7b45315af1f47708a045fd86dce4988fd54f63ed Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 04:15:33 +0200 Subject: [PATCH 136/258] Avoid C4996 in sv_copy_test.cpp --- test/sv_copy_test.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/sv_copy_test.cpp b/test/sv_copy_test.cpp index 8dbd860..75abe88 100644 --- a/test/sv_copy_test.cpp +++ b/test/sv_copy_test.cpp @@ -2,6 +2,8 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt +#define _SCL_SECURE_NO_WARNINGS + #include #include #include From f94db671f63498348a29ce7d8f8ef72785a84be4 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 04:17:51 +0200 Subject: [PATCH 137/258] Disable C4702 in lightweight_test_fail6, no_exceptions_support_test --- test/lightweight_test_fail6.cpp | 4 ++++ test/no_exceptions_support_test.cpp | 1 + 2 files changed, 5 insertions(+) diff --git a/test/lightweight_test_fail6.cpp b/test/lightweight_test_fail6.cpp index f73a6df..4296f5c 100644 --- a/test/lightweight_test_fail6.cpp +++ b/test/lightweight_test_fail6.cpp @@ -8,6 +8,10 @@ // http://www.boost.org/LICENSE_1_0.txt // +#if defined(_MSC_VER) +# pragma warning(disable: 4702) // unreachable code +#endif + #include struct X diff --git a/test/no_exceptions_support_test.cpp b/test/no_exceptions_support_test.cpp index 7e227b9..6cce8ae 100644 --- a/test/no_exceptions_support_test.cpp +++ b/test/no_exceptions_support_test.cpp @@ -11,6 +11,7 @@ #if defined(_MSC_VER) # pragma warning(disable: 4530) // C++ exception handler used # pragma warning(disable: 4577) // noexcept used without /EHsc +# pragma warning(disable: 4702) // unreachable code #endif #include From ef3505db59ffdadf4d2f0acb5ba5ff45b5505aea Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 1 Nov 2021 04:44:07 +0200 Subject: [PATCH 138/258] Disable -Wtype-limits for g++ 4.4 in Jamfile --- test/Jamfile.v2 | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 510db53..0b6e54b 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -287,10 +287,14 @@ run sv_starts_with_test.cpp ; run sv_ends_with_test.cpp ; run sv_find_test.cpp ; run sv_rfind_test.cpp ; -run sv_find_first_of_test.cpp ; -run sv_find_last_of_test.cpp ; -run sv_find_first_not_of_test.cpp ; -run sv_find_last_not_of_test.cpp ; +run sv_find_first_of_test.cpp + : : : gcc-4.4:-Wno-type-limits ; +run sv_find_last_of_test.cpp + : : : gcc-4.4:-Wno-type-limits ; +run sv_find_first_not_of_test.cpp + : : : gcc-4.4:-Wno-type-limits ; +run sv_find_last_not_of_test.cpp + : : : gcc-4.4:-Wno-type-limits ; run sv_contains_test.cpp ; run sv_eq_test.cpp ; run sv_lt_test.cpp ; From a4172b431999ec5f5f4cd0884b7c9d145661d949 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Mon, 1 Nov 2021 06:31:51 -0400 Subject: [PATCH 139/258] MSVC warning workaround for empty_value --- include/boost/core/empty_value.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/boost/core/empty_value.hpp b/include/boost/core/empty_value.hpp index 2ac2331..9dfd442 100644 --- a/include/boost/core/empty_value.hpp +++ b/include/boost/core/empty_value.hpp @@ -25,6 +25,11 @@ Distributed under the Boost Software License, Version 1.0. #endif #endif +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:4510) +#endif + namespace boost { template @@ -143,4 +148,8 @@ BOOST_INLINE_CONSTEXPR empty_init_t empty_init = empty_init_t(); } /* boost */ +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + #endif From 213e4695bfe17184f78c1a337ed3f497b2d7a269 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Mon, 1 Nov 2021 00:02:39 +0300 Subject: [PATCH 140/258] Use C++17 if constexpr where possible. --- include/boost/core/bit.hpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/boost/core/bit.hpp b/include/boost/core/bit.hpp index f4305b9..3b31bdb 100644 --- a/include/boost/core/bit.hpp +++ b/include/boost/core/bit.hpp @@ -171,15 +171,15 @@ int countl_zero( T x ) BOOST_NOEXCEPT { BOOST_STATIC_ASSERT( sizeof(T) == sizeof(boost::uint8_t) || sizeof(T) == sizeof(boost::uint16_t) || sizeof(T) == sizeof(boost::uint32_t) || sizeof(T) == sizeof(boost::uint64_t) ); - if( sizeof(T) == sizeof(boost::uint8_t) ) + BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint8_t) ) { return boost::core::detail::countl_impl( static_cast( x ) ); } - else if( sizeof(T) == sizeof(boost::uint16_t) ) + else BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint16_t) ) { return boost::core::detail::countl_impl( static_cast( x ) ); } - else if( sizeof(T) == sizeof(boost::uint32_t) ) + else BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint32_t) ) { return boost::core::detail::countl_impl( static_cast( x ) ); } @@ -306,15 +306,15 @@ int countr_zero( T x ) BOOST_NOEXCEPT { BOOST_STATIC_ASSERT( sizeof(T) == sizeof(boost::uint8_t) || sizeof(T) == sizeof(boost::uint16_t) || sizeof(T) == sizeof(boost::uint32_t) || sizeof(T) == sizeof(boost::uint64_t) ); - if( sizeof(T) == sizeof(boost::uint8_t) ) + BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint8_t) ) { return boost::core::detail::countr_impl( static_cast( x ) ); } - else if( sizeof(T) == sizeof(boost::uint16_t) ) + else BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint16_t) ) { return boost::core::detail::countr_impl( static_cast( x ) ); } - else if( sizeof(T) == sizeof(boost::uint32_t) ) + else BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint32_t) ) { return boost::core::detail::countr_impl( static_cast( x ) ); } @@ -410,7 +410,7 @@ BOOST_CXX14_CONSTEXPR int popcount( T x ) BOOST_NOEXCEPT { BOOST_STATIC_ASSERT( sizeof(T) <= sizeof(boost::uint64_t) ); - if( sizeof(T) <= sizeof(boost::uint32_t) ) + BOOST_IF_CONSTEXPR ( sizeof(T) <= sizeof(boost::uint32_t) ) { return boost::core::detail::popcount_impl( static_cast( x ) ); } @@ -509,7 +509,7 @@ BOOST_CXX14_CONSTEXPR T bit_ceil( T x ) BOOST_NOEXCEPT { BOOST_STATIC_ASSERT( sizeof(T) <= sizeof(boost::uint64_t) ); - if( sizeof(T) <= sizeof(boost::uint32_t) ) + BOOST_IF_CONSTEXPR ( sizeof(T) <= sizeof(boost::uint32_t) ) { return static_cast( boost::core::detail::bit_ceil_impl( static_cast( x ) ) ); } From a1ad1784bfc21133f4d83fbf47dda961bb4a7c31 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Tue, 16 Nov 2021 00:36:15 +0300 Subject: [PATCH 141/258] Updated check for apt-add-repository capabilities. In Ubuntu 20.04 there appeared an updated version of the software-properties-common package in focal-updates, which ships a newer apt-add-repository version that doesn't support -P/-S/-U command line arguments. Since we cannot rely on package version checks to determine apt-add-repository capabilities, we have to parse its --help output instead. Also, made source list processing more protected against spaces. --- .github/workflows/ci.yml | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 705e8a0..f338a8d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -252,7 +252,7 @@ jobs: if [ -f "/etc/debian_version" ] then apt-get -o Acquire::Retries=$NET_RETRY_COUNT update - apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y sudo software-properties-common tzdata wget curl apt-transport-https ca-certificates make build-essential g++ python python3 git cmake + apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y sudo software-properties-common tzdata wget curl apt-transport-https ca-certificates make build-essential g++ python python3 perl git cmake fi fi git config --global pack.threads 0 @@ -262,28 +262,32 @@ jobs: - name: Install packages if: matrix.install run: | - SOURCE_KEYS=(${{join(matrix.source_keys, ' ')}}) - SOURCES=(${{join(matrix.sources, ' ')}}) + declare -a SOURCE_KEYS SOURCES + if [ -n "${{join(matrix.source_keys, ' ')}}" ] + then + SOURCE_KEYS=("${{join(matrix.source_keys, '" "')}}") + fi + if [ -n "${{join(matrix.sources, ' ')}}" ] + then + SOURCES=("${{join(matrix.sources, '" "')}}") + fi for key in "${SOURCE_KEYS[@]}" do for i in {1..$NET_RETRY_COUNT} do + echo "Adding key: $key" wget -O - "$key" | sudo apt-key add - && break || sleep 2 done done if [ ${#SOURCES[@]} -gt 0 ] then APT_ADD_REPO_COMMON_ARGS=("-y") - APT_ADD_REPO_HAS_SOURCE_ARGS=0 - SOFTWARE_PROPERTIES_VERSION="$(dpkg-query --showformat='${Version}' --show software-properties-common)" - if dpkg --compare-versions "$SOFTWARE_PROPERTIES_VERSION" ge "0.96.24.20" + APT_ADD_REPO_SUPPORTED_ARGS="$(apt-add-repository --help | perl -ne 'if (/^\s*-n/) { print "n"; } elsif (/^\s*-P/) { print "P"; } elsif (/^\s*-S/) { print "S"; } elsif (/^\s*-U/) { print "U"; }')" + if [ -n "$APT_ADD_REPO_SUPPORTED_ARGS" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*n*}" ] then APT_ADD_REPO_COMMON_ARGS+=("-n") fi - if dpkg --compare-versions "$SOFTWARE_PROPERTIES_VERSION" ge "0.98.10" - then - APT_ADD_REPO_HAS_SOURCE_ARGS=1 - fi + APT_ADD_REPO_HAS_SOURCE_ARGS="$([ -n "$APT_ADD_REPO_SUPPORTED_ARGS" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*P*}" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*S*}" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*U*}" ] && echo 1 || echo 0)" for source in "${SOURCES[@]}" do for i in {1..$NET_RETRY_COUNT} @@ -304,6 +308,7 @@ jobs: esac fi APT_ADD_REPO_ARGS+=("$source") + echo "apt-add-repository ${APT_ADD_REPO_ARGS[@]}" sudo -E apt-add-repository "${APT_ADD_REPO_ARGS[@]}" && break || sleep 2 done done @@ -334,7 +339,7 @@ jobs: REF=${GITHUB_BASE_REF:-$GITHUB_REF} REF=${REF#refs/heads/} echo REF: $REF - BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true + BOOST_BRANCH=develop && [ "$REF" = "master" ] && BOOST_BRANCH=master || true echo BOOST_BRANCH: $BOOST_BRANCH BUILD_JOBS=$((nproc || sysctl -n hw.ncpu) 2> /dev/null) echo "BUILD_JOBS=$BUILD_JOBS" >> $GITHUB_ENV From 74c770206a9f7b5ea93d6c84c10356130d6940f8 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Thu, 2 Dec 2021 23:03:11 -0500 Subject: [PATCH 142/258] Allow all individual traits to be specialized --- include/boost/core/allocator_access.hpp | 188 ++++++++++++++++++------ 1 file changed, 139 insertions(+), 49 deletions(-) diff --git a/include/boost/core/allocator_access.hpp b/include/boost/core/allocator_access.hpp index 764c122..37c2b7a 100644 --- a/include/boost/core/allocator_access.hpp +++ b/include/boost/core/allocator_access.hpp @@ -43,24 +43,29 @@ struct allocator_pointer { typedef typename A::pointer type; }; #else +namespace detail { + template -struct allocator_pointer { +struct alloc_ptr { typedef typename A::value_type* type; }; -namespace detail { - template struct alloc_void { typedef void type; }; +template +struct alloc_ptr::type> { + typedef typename A::pointer type; +}; + } /* detail */ template -struct allocator_pointer::type> { - typedef typename A::pointer type; +struct allocator_pointer { + typedef typename detail::alloc_ptr::type type; }; #endif @@ -70,18 +75,27 @@ struct allocator_const_pointer { typedef typename A::const_pointer type; }; #else +namespace detail { + template -struct allocator_const_pointer { - typedef typename pointer_traits::type>::template +struct alloc_const_ptr { + typedef typename boost::pointer_traits::type>::template rebind_to::type type; }; template -struct allocator_const_pointer::type> { +struct alloc_const_ptr::type> { typedef typename A::const_pointer type; }; + +} /* detail */ + +template +struct allocator_const_pointer { + typedef typename detail::alloc_const_ptr::type type; +}; #endif #if defined(BOOST_NO_CXX11_ALLOCATOR) @@ -90,18 +104,27 @@ struct allocator_void_pointer { typedef typename A::template rebind::other::pointer type; }; #else +namespace detail { + template -struct allocator_void_pointer { - typedef typename pointer_traits::type>::template +struct alloc_void_ptr { + typedef typename boost::pointer_traits::type>::template rebind_to::type type; }; template -struct allocator_void_pointer::type> { +struct alloc_void_ptr::type> { typedef typename A::void_pointer type; }; + +} /* detail */ + +template +struct allocator_void_pointer { + typedef typename detail::alloc_void_ptr::type type; +}; #endif #if defined(BOOST_NO_CXX11_ALLOCATOR) @@ -110,18 +133,27 @@ struct allocator_const_void_pointer { typedef typename A::template rebind::other::const_pointer type; }; #else +namespace detail { + template -struct allocator_const_void_pointer { - typedef typename pointer_traits::type>::template +struct alloc_const_void_ptr { + typedef typename boost::pointer_traits::type>::template rebind_to::type type; }; template -struct allocator_const_void_pointer::type> { +struct alloc_const_void_ptr::type> { typedef typename A::const_void_pointer type; }; + +} /* detail */ + +template +struct allocator_const_void_pointer { + typedef typename detail::alloc_const_void_ptr::type type; +}; #endif #if defined(BOOST_NO_CXX11_ALLOCATOR) @@ -130,17 +162,26 @@ struct allocator_difference_type { typedef typename A::difference_type type; }; #else +namespace detail { + template -struct allocator_difference_type { - typedef typename pointer_traits::type>::difference_type type; +struct alloc_diff_type { + typedef typename boost::pointer_traits::type>::difference_type type; }; template -struct allocator_difference_type::type> { +struct alloc_diff_type::type> { typedef typename A::difference_type type; }; + +} /* detail */ + +template +struct allocator_difference_type { + typedef typename detail::alloc_diff_type::type type; +}; #endif #if defined(BOOST_NO_CXX11_ALLOCATOR) @@ -149,17 +190,26 @@ struct allocator_size_type { typedef typename A::size_type type; }; #else +namespace detail { + template -struct allocator_size_type { +struct alloc_size_type { typedef typename std::make_unsigned::type>::type type; + boost::allocator_difference_type::type>::type type; }; template -struct allocator_size_type::type> { +struct alloc_size_type::type> { typedef typename A::size_type type; }; + +} /* detail */ + +template +struct allocator_size_type { + typedef typename detail::alloc_size_type::type type; +}; #endif #if defined(BOOST_NO_CXX11_ALLOCATOR) @@ -176,17 +226,26 @@ struct allocator_propagate_on_container_copy_assignment { typedef detail::alloc_false type; }; #else +namespace detail { + template -struct allocator_propagate_on_container_copy_assignment { +struct alloc_pocca { typedef std::false_type type; }; template -struct allocator_propagate_on_container_copy_assignment::type> { typedef typename A::propagate_on_container_copy_assignment type; }; + +} /* detail */ + +template +struct allocator_propagate_on_container_copy_assignment { + typedef typename detail::alloc_pocca::type type; +}; #endif #if defined(BOOST_NO_CXX11_ALLOCATOR) @@ -195,17 +254,26 @@ struct allocator_propagate_on_container_move_assignment { typedef detail::alloc_false type; }; #else +namespace detail { + template -struct allocator_propagate_on_container_move_assignment { +struct alloc_pocma { typedef std::false_type type; }; template -struct allocator_propagate_on_container_move_assignment::type> { typedef typename A::propagate_on_container_move_assignment type; }; + +} /* detail */ + +template +struct allocator_propagate_on_container_move_assignment { + typedef typename detail::alloc_pocma::type type; +}; #endif #if defined(BOOST_NO_CXX11_ALLOCATOR) @@ -214,17 +282,25 @@ struct allocator_propagate_on_container_swap { typedef detail::alloc_false type; }; #else +namespace detail { + template -struct allocator_propagate_on_container_swap { +struct alloc_pocs { typedef std::false_type type; }; template -struct allocator_propagate_on_container_swap::type> { +struct alloc_pocs::type> { typedef typename A::propagate_on_container_swap type; }; + +} /* detail */ + +template +struct allocator_propagate_on_container_swap { + typedef typename detail::alloc_pocs::type type; +}; #endif #if defined(BOOST_NO_CXX11_ALLOCATOR) @@ -233,16 +309,25 @@ struct allocator_is_always_equal { typedef detail::alloc_false type; }; #else +namespace detail { + template -struct allocator_is_always_equal { +struct alloc_equal { typedef typename std::is_empty::type type; }; template -struct allocator_is_always_equal::type> { +struct alloc_equal::type> { typedef typename A::is_always_equal type; }; + +} /* detail */ + +template +struct allocator_is_always_equal { + typedef typename detail::alloc_equal::type type; +}; #endif #if defined(BOOST_NO_CXX11_ALLOCATOR) @@ -261,18 +346,23 @@ struct alloc_to, T> { typedef A type; }; -} /* detail */ - template -struct allocator_rebind { - typedef typename detail::alloc_to::type type; +struct alloc_rebind { + typedef typename alloc_to::type type; }; template -struct allocator_rebind::other>::type> { +struct alloc_rebind::other>::type> { typedef typename A::template rebind::other type; }; + +} /* detail */ + +template +struct allocator_rebind { + typedef typename detail::alloc_rebind::type type; +}; #endif template From c8b989d80b41f184b53c7ff9589506c99953f921 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Thu, 2 Dec 2021 23:39:47 -0500 Subject: [PATCH 143/258] Add allocator_traits that uses allocator_access --- doc/allocator_traits.qbk | 116 ++++++++++++++++++++++++ doc/changes.qbk | 6 ++ doc/core.qbk | 1 + include/boost/core/allocator_traits.hpp | 112 +++++++++++++++++++++++ test/Jamfile.v2 | 1 + test/allocator_traits_test.cpp | 114 +++++++++++++++++++++++ 6 files changed, 350 insertions(+) create mode 100644 doc/allocator_traits.qbk create mode 100644 include/boost/core/allocator_traits.hpp create mode 100644 test/allocator_traits_test.cpp diff --git a/doc/allocator_traits.qbk b/doc/allocator_traits.qbk new file mode 100644 index 0000000..3b20d32 --- /dev/null +++ b/doc/allocator_traits.qbk @@ -0,0 +1,116 @@ +[/ +Copyright 2021 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +] + +[section:allocator_traits allocator_traits] + +[simplesect Authors] + +* Glen Fernandes + +[endsimplesect] + +[section Overview] + +This header provides an implementation of the +C++ standard library class template `allocator_traits` based on the facilities +in [link core.allocator_access Allocator Access]. Users should still prefer the +individual traits, but this utility exists to simplify migration. + +[endsect] + +[section Reference] + +``` +namespace boost { + +template +struct allocator_traits { + using allocator_type = A; + + using value_type = allocator_value_type_t; + + using pointer = allocator_pointer_t; + + using const_pointer = allocator_const_pointer_t; + + using void_pointer = allocator_void_pointer_t; + + using const_pointer = allocator_const_void_pointer_t; + + using difference_type = allocator_difference_type_t; + + using size_type = allocator_size_type_t; + + using propagate_on_container_copy_assignment = + allocator_propagate_on_container_copy_assignment_t; + + using propagate_on_container_move_assignment = + allocator_propagate_on_container_move_assignment_t; + + using propagate_on_container_swap = + allocator_propagate_on_container_swap_t; + + using is_always_equal = allocator_is_always_equal_t; + + template + using rebind_traits = allocator_traits >; + + static pointer allocate(A& a, size_type n); + + static pointer allocate(A& a, size_type n, const_void_pointer h); + + static void deallocate(A& a, pointer p, size_type n); + + template + static void construct(A& a, T* p, Args&&... args); + + static void destroy(A& a, T* p); + + static size_type max_size(const A& a) noexcept; + + static A select_on_container_copy_construction(const A& a); +}; + +} /* boost */ +``` + +[section Static member functions] + +[variablelist +[[`static pointer allocate(A& a, size_type n);`] +[Equivalent to: `return boost::allocator_allocate(a, n);`]] +[[`static pointer allocate(A& a, size_type n, const_void_pointer h);`] +[Equivalent to: `return boost::allocator_allocate(a, n, h);`]] +[[`static void deallocate(A& a, pointer p, size_type n);`] +[Equivalent to: `return boost::allocator_deallocate(a, n, h);`]] +[[`template +static void construct(A& a, T* p, Args&&... args);`] +[Equivalent to: +`return boost::allocator_construct(a, p, std::forward(args)...);`]] +[[`static void destroy(A& a, T* p);`] +[Equivalent to: `return boost::allocator_destroy(a, p);`]] +[[`static size_type max_size(const A& a);`] +[Equivalent to: `return boost::allocator_max_size(a);`]] +[[`static A select_on_container_copy_construction(const A& a);`] +[Equivalent to: +`return boost::allocator_select_on_container_copy_construction(a);`]]] + +[endsect] + +[section Notes] + +# The member `rebind_alloc` is not provided for parity with C++03 where it is +unimplementable. Instead of `allocator_traits::rebind_alloc` you can +express the same with `allocator_traits::rebind_traits::allocator_type` +or more simply with `allocator_rebind_t`. + +[endsect] + +[endsect] + +[endsect] diff --git a/doc/changes.qbk b/doc/changes.qbk index 5168026..e809ee9 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -6,6 +6,12 @@ [section Revision History] +[section Changes in 1.79.0] + +* Added `boost::allocator_traits`, an implementation of `std::allocator_traits`. + +[endsect] + [section Changes in 1.78.0] * Added a generic implementation to `boost/core/cmath.hpp`, enabled when `BOOST_CORE_USE_GENERIC_CMATH` diff --git a/doc/core.qbk b/doc/core.qbk index 7f7a75b..fbbecf6 100644 --- a/doc/core.qbk +++ b/doc/core.qbk @@ -42,6 +42,7 @@ criteria for inclusion is that the utility component be: [include addressof.qbk] [include allocator_access.qbk] +[include allocator_traits.qbk] [include alloc_construct.qbk] [include bit.qbk] [include checked_delete.qbk] diff --git a/include/boost/core/allocator_traits.hpp b/include/boost/core/allocator_traits.hpp new file mode 100644 index 0000000..bf8749d --- /dev/null +++ b/include/boost/core/allocator_traits.hpp @@ -0,0 +1,112 @@ +/* +Copyright 2021 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_CORE_ALLOCATOR_TRAITS_HPP +#define BOOST_CORE_ALLOCATOR_TRAITS_HPP + +#include + +namespace boost { + +template +struct allocator_traits { + typedef A allocator_type; + + typedef typename allocator_value_type::type value_type; + + typedef typename allocator_pointer::type pointer; + + typedef typename allocator_const_pointer::type const_pointer; + + typedef typename allocator_void_pointer::type void_pointer; + + typedef typename allocator_const_void_pointer::type const_void_pointer; + + typedef typename allocator_difference_type::type difference_type; + + typedef typename allocator_size_type::type size_type; + + typedef typename allocator_propagate_on_container_copy_assignment::type + propagate_on_container_copy_assignment; + + typedef typename allocator_propagate_on_container_move_assignment::type + propagate_on_container_move_assignment; + + typedef typename allocator_propagate_on_container_swap::type + propagate_on_container_swap; + + typedef typename allocator_is_always_equal::type is_always_equal; + +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + template + using rebind_traits = allocator_traits::type>; +#else + template + struct rebind_traits + : allocator_traits::type> { }; +#endif + + static pointer allocate(A& a, size_type n) { + return boost::allocator_allocate(a, n); + } + + static pointer allocate(A& a, size_type n, const_void_pointer h) { + return boost::allocator_allocate(a, n, h); + } + + static void deallocate(A& a, pointer p, size_type n) { + return boost::allocator_deallocate(a, p, n); + } + + template + static void construct(A& a, T* p) { + boost::allocator_construct(a, p); + } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template + static void construct(A& a, T* p, V&& v, Args&&... args) { + boost::allocator_construct(a, p, std::forward(v), + std::forward(args)...); + } +#else + template + static void construct(A& a, T* p, V&& v) { + boost::allocator_construct(a, p, std::forward(v)); + } +#endif +#else + template + static void construct(A& a, T* p, const V& v) { + boost::allocator_construct(a, p, v); + } + + template + static void construct(A& a, T* p, V& v) { + boost::allocator_construct(a, p, v); + } +#endif + + template + static void destroy(A& a, T* p) { + boost::allocator_destroy(a, p); + } + + static size_type max_size(const A& a) BOOST_NOEXCEPT { + return boost::allocator_max_size(a); + } + + static A select_on_container_copy_construction(const A& a) { + return boost::allocator_select_on_container_copy_construction(a); + } +}; + +} /* boost */ + +#endif diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 0b6e54b..0518bdc 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -236,6 +236,7 @@ run allocator_allocate_hint_test.cpp ; run allocator_deallocate_test.cpp ; run allocator_max_size_test.cpp ; run allocator_soccc_test.cpp ; +run allocator_traits_test.cpp ; lib lib_typeid : lib_typeid.cpp : shared:LIB_TYPEID_DYN_LINK=1 ; diff --git a/test/allocator_traits_test.cpp b/test/allocator_traits_test.cpp new file mode 100644 index 0000000..89a67e8 --- /dev/null +++ b/test/allocator_traits_test.cpp @@ -0,0 +1,114 @@ +/* +Copyright 2021 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include + +template +class creator { +public: + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef void* void_pointer; + typedef const void* const_void_pointer; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + template + struct rebind { + typedef creator other; + }; + + explicit creator(int value) BOOST_NOEXCEPT + : state_(value) { } + + template + creator(const creator& other) BOOST_NOEXCEPT + : state_(other.state) { } + + std::size_t max_size() const BOOST_NOEXCEPT { + return static_cast(-1) / sizeof(T); + } + + T* allocate(std::size_t n, const void* = 0) { + return static_cast(::operator new(sizeof(T) * n)); + } + + void deallocate(T* p, std::size_t) { + ::operator delete(p); + } + + int state() const { + return state_; + } + +private: + int state_; +}; + +template +inline bool operator==(const creator& lhs, + const creator& rhs) BOOST_NOEXCEPT +{ + return lhs.state() == rhs.state(); +} + +template +inline bool operator!=(const creator& lhs, + const creator& rhs) BOOST_NOEXCEPT +{ + return !(lhs == rhs); +} + +int main() +{ + BOOST_TEST_TRAIT_SAME(creator, + boost::allocator_traits >::allocator_type); + BOOST_TEST_TRAIT_SAME(int, + boost::allocator_traits >::value_type); + BOOST_TEST_TRAIT_SAME(int*, + boost::allocator_traits >::pointer); + BOOST_TEST_TRAIT_SAME(const int*, + boost::allocator_traits >::const_pointer); + BOOST_TEST_TRAIT_SAME(void*, + boost::allocator_traits >::void_pointer); + BOOST_TEST_TRAIT_SAME(const void*, + boost::allocator_traits >::const_void_pointer); + BOOST_TEST_TRAIT_SAME(std::ptrdiff_t, + boost::allocator_traits >::difference_type); + BOOST_TEST_TRAIT_SAME(std::size_t, + boost::allocator_traits >::size_type); + BOOST_TEST_TRAIT_FALSE((boost::allocator_traits >:: + propagate_on_container_copy_assignment)); + BOOST_TEST_TRAIT_FALSE((boost::allocator_traits >:: + propagate_on_container_move_assignment)); + BOOST_TEST_TRAIT_FALSE((boost::allocator_traits >:: + propagate_on_container_swap)); + BOOST_TEST_TRAIT_FALSE((boost::allocator_traits >:: + is_always_equal)); + BOOST_TEST_TRAIT_SAME(creator, + boost::allocator_traits >:: + rebind_traits::allocator_type); + creator a(1); + int* p1 = boost::allocator_traits >::allocate(a, 1); + if (BOOST_TEST(p1)) { + int* p2 = boost::allocator_traits >::allocate(a, 1, p1); + if (BOOST_TEST(p2)) { + boost::allocator_traits >::deallocate(a, p2, 1); + } + boost::allocator_traits >::construct(a, p1, 5); + BOOST_TEST_EQ(*p1, 5); + boost::allocator_traits >::destroy(a, p1); + boost::allocator_traits >::deallocate(a, p1, 1); + } + BOOST_TEST_EQ(boost::allocator_traits >::max_size(a), + static_cast(-1) / sizeof(int)); + BOOST_TEST(boost::allocator_traits >:: + select_on_container_copy_construction(a) == a); + return boost::report_errors(); +} From c1be2097d7f0e919767c95b8c5ae256cf6a1e5a8 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Sat, 4 Dec 2021 00:22:51 -0500 Subject: [PATCH 144/258] Minor documentation changes --- doc/allocator_traits.qbk | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/allocator_traits.qbk b/doc/allocator_traits.qbk index 3b20d32..f04a62b 100644 --- a/doc/allocator_traits.qbk +++ b/doc/allocator_traits.qbk @@ -87,14 +87,14 @@ struct allocator_traits { [[`static pointer allocate(A& a, size_type n, const_void_pointer h);`] [Equivalent to: `return boost::allocator_allocate(a, n, h);`]] [[`static void deallocate(A& a, pointer p, size_type n);`] -[Equivalent to: `return boost::allocator_deallocate(a, n, h);`]] +[Equivalent to: `boost::allocator_deallocate(a, n, h);`]] [[`template static void construct(A& a, T* p, Args&&... args);`] [Equivalent to: -`return boost::allocator_construct(a, p, std::forward(args)...);`]] +`boost::allocator_construct(a, p, std::forward(args)...);`]] [[`static void destroy(A& a, T* p);`] -[Equivalent to: `return boost::allocator_destroy(a, p);`]] -[[`static size_type max_size(const A& a);`] +[Equivalent to: `boost::allocator_destroy(a, p);`]] +[[`static size_type max_size(const A& a) noexcept;`] [Equivalent to: `return boost::allocator_max_size(a);`]] [[`static A select_on_container_copy_construction(const A& a);`] [Equivalent to: From 46f37b2f16576bf9e978b073ffa4ede65dccf303 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Sat, 4 Dec 2021 00:24:45 -0500 Subject: [PATCH 145/258] Make max_size noexcept --- include/boost/core/allocator_access.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/core/allocator_access.hpp b/include/boost/core/allocator_access.hpp index 37c2b7a..edf749d 100644 --- a/include/boost/core/allocator_access.hpp +++ b/include/boost/core/allocator_access.hpp @@ -551,7 +551,7 @@ allocator_destroy(A&, T* p) #if defined(BOOST_NO_CXX11_ALLOCATOR) template inline typename allocator_size_type::type -allocator_max_size(const A& a) +allocator_max_size(const A& a) BOOST_NOEXCEPT { return a.max_size(); } @@ -576,7 +576,7 @@ public: template inline typename std::enable_if::value, typename allocator_size_type::type>::type -allocator_max_size(const A& a) +allocator_max_size(const A& a) BOOST_NOEXCEPT { return a.max_size(); } @@ -584,7 +584,7 @@ allocator_max_size(const A& a) template inline typename std::enable_if::value, typename allocator_size_type::type>::type -allocator_max_size(const A&) +allocator_max_size(const A&) BOOST_NOEXCEPT { return (std::numeric_limits::type>::max)() / sizeof(typename A::value_type); From 15f7fb7eaa440f7c9e8822636a3afa6905e7d495 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Sat, 4 Dec 2021 00:32:27 -0500 Subject: [PATCH 146/258] Move Notes to a top level section --- doc/allocator_traits.qbk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/allocator_traits.qbk b/doc/allocator_traits.qbk index f04a62b..6372cbb 100644 --- a/doc/allocator_traits.qbk +++ b/doc/allocator_traits.qbk @@ -102,6 +102,8 @@ static void construct(A& a, T* p, Args&&... args);`] [endsect] +[endsect] + [section Notes] # The member `rebind_alloc` is not provided for parity with C++03 where it is @@ -112,5 +114,3 @@ or more simply with `allocator_rebind_t`. [endsect] [endsect] - -[endsect] From 15c884438c30d9ba1c4b950f1eeef34f641eab5b Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Sat, 4 Dec 2021 14:38:18 -0500 Subject: [PATCH 147/258] Correct note in documentation --- doc/allocator_traits.qbk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/allocator_traits.qbk b/doc/allocator_traits.qbk index 6372cbb..f16cc70 100644 --- a/doc/allocator_traits.qbk +++ b/doc/allocator_traits.qbk @@ -109,7 +109,7 @@ static void construct(A& a, T* p, Args&&... args);`] # The member `rebind_alloc` is not provided for parity with C++03 where it is unimplementable. Instead of `allocator_traits::rebind_alloc` you can express the same with `allocator_traits::rebind_traits::allocator_type` -or more simply with `allocator_rebind_t`. +or more simply with `allocator_rebind_t`. [endsect] From 8985ce604e5b410c6f5899569066568ab3faa393 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Sat, 4 Dec 2021 14:39:36 -0500 Subject: [PATCH 148/258] Simplify test --- test/allocator_traits_test.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/allocator_traits_test.cpp b/test/allocator_traits_test.cpp index 89a67e8..f8f0939 100644 --- a/test/allocator_traits_test.cpp +++ b/test/allocator_traits_test.cpp @@ -97,15 +97,15 @@ int main() creator a(1); int* p1 = boost::allocator_traits >::allocate(a, 1); if (BOOST_TEST(p1)) { - int* p2 = boost::allocator_traits >::allocate(a, 1, p1); - if (BOOST_TEST(p2)) { - boost::allocator_traits >::deallocate(a, p2, 1); - } boost::allocator_traits >::construct(a, p1, 5); BOOST_TEST_EQ(*p1, 5); boost::allocator_traits >::destroy(a, p1); boost::allocator_traits >::deallocate(a, p1, 1); } + int* p2 = boost::allocator_traits >::allocate(a, 1, 0); + if (BOOST_TEST(p2)) { + boost::allocator_traits >::deallocate(a, p2, 1); + } BOOST_TEST_EQ(boost::allocator_traits >::max_size(a), static_cast(-1) / sizeof(int)); BOOST_TEST(boost::allocator_traits >:: From febc1950935cb85f66fc6ed276016c667a333552 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Sat, 4 Dec 2021 14:41:23 -0500 Subject: [PATCH 149/258] Add default_allocator allocate hint overload in C++03 mode --- include/boost/core/default_allocator.hpp | 6 ++++++ test/Jamfile.v2 | 1 + test/default_allocator_allocate_hint_test.cpp | 19 +++++++++++++++++++ 3 files changed, 26 insertions(+) create mode 100644 test/default_allocator_allocate_hint_test.cpp diff --git a/include/boost/core/default_allocator.hpp b/include/boost/core/default_allocator.hpp index 9e466ca..ba8540b 100644 --- a/include/boost/core/default_allocator.hpp +++ b/include/boost/core/default_allocator.hpp @@ -108,6 +108,12 @@ struct default_allocator { } #endif +#if defined(BOOST_NO_CXX11_ALLOCATOR) + T* allocate(std::size_t n, const void*) { + return allocate(n); + } +#endif + #if (defined(BOOST_LIBSTDCXX_VERSION) && BOOST_LIBSTDCXX_VERSION < 60000) || \ defined(BOOST_NO_CXX11_ALLOCATOR) template diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 0518bdc..58d46f5 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -211,6 +211,7 @@ run default_allocator_test.cpp msvc:on gcc:on clang:on ; +run default_allocator_allocate_hint_test.cpp ; run noinit_adaptor_test.cpp ; run alloc_construct_test.cpp ; diff --git a/test/default_allocator_allocate_hint_test.cpp b/test/default_allocator_allocate_hint_test.cpp new file mode 100644 index 0000000..fed2c90 --- /dev/null +++ b/test/default_allocator_allocate_hint_test.cpp @@ -0,0 +1,19 @@ +/* +Copyright 2021 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include +#include + +int main() +{ + boost::default_allocator a; + int* p = boost::allocator_allocate(a, 1, 0); + BOOST_TEST(p != 0); + a.deallocate(p, 1); + return boost::report_errors(); +} From 6b3fb219cc25c9dffa2e94ab4175c1a9997d8739 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Mon, 6 Dec 2021 15:58:48 -0500 Subject: [PATCH 150/258] Minor refactoring in allocator access --- include/boost/core/allocator_access.hpp | 81 +++++++++++++------------ 1 file changed, 42 insertions(+), 39 deletions(-) diff --git a/include/boost/core/allocator_access.hpp b/include/boost/core/allocator_access.hpp index edf749d..5caba94 100644 --- a/include/boost/core/allocator_access.hpp +++ b/include/boost/core/allocator_access.hpp @@ -47,7 +47,7 @@ namespace detail { template struct alloc_ptr { - typedef typename A::value_type* type; + typedef typename allocator_value_type::type* type; }; template @@ -98,10 +98,46 @@ struct allocator_const_pointer { }; #endif +#if defined(BOOST_NO_CXX11_ALLOCATOR) +template +struct allocator_rebind { + typedef typename A::template rebind::other type; +}; +#else +namespace detail { + +template +struct alloc_to { }; + +template class A, class T, class U, class... V> +struct alloc_to, T> { + typedef A type; +}; + +template +struct alloc_rebind { + typedef typename alloc_to::type type; +}; + +template +struct alloc_rebind::other>::type> { + typedef typename A::template rebind::other type; +}; + +} /* detail */ + +template +struct allocator_rebind { + typedef typename detail::alloc_rebind::type type; +}; +#endif + #if defined(BOOST_NO_CXX11_ALLOCATOR) template struct allocator_void_pointer { - typedef typename A::template rebind::other::pointer type; + typedef typename allocator_pointer::type>::type type; }; #else namespace detail { @@ -130,7 +166,8 @@ struct allocator_void_pointer { #if defined(BOOST_NO_CXX11_ALLOCATOR) template struct allocator_const_void_pointer { - typedef typename A::template rebind::other::const_pointer type; + typedef typename allocator_const_pointer::type>::type type; }; #else namespace detail { @@ -330,41 +367,6 @@ struct allocator_is_always_equal { }; #endif -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_rebind { - typedef typename A::template rebind::other type; -}; -#else -namespace detail { - -template -struct alloc_to { }; - -template class A, class T, class U, class... V> -struct alloc_to, T> { - typedef A type; -}; - -template -struct alloc_rebind { - typedef typename alloc_to::type type; -}; - -template -struct alloc_rebind::other>::type> { - typedef typename A::template rebind::other type; -}; - -} /* detail */ - -template -struct allocator_rebind { - typedef typename detail::alloc_rebind::type type; -}; -#endif - template inline typename allocator_pointer::type allocator_allocate(A& a, typename allocator_size_type::type n) @@ -587,7 +589,8 @@ inline typename std::enable_if::value, allocator_max_size(const A&) BOOST_NOEXCEPT { return (std::numeric_limits::type>::max)() / sizeof(typename A::value_type); + allocator_size_type::type>::max)() / + sizeof(typename allocator_value_type::type); } #endif From 5abadf4472ad03de8ef11b6727be4495bf1687ab Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Mon, 6 Dec 2021 16:35:37 -0500 Subject: [PATCH 151/258] Change A::value_type to allocator_value_type --- include/boost/core/allocator_access.hpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/include/boost/core/allocator_access.hpp b/include/boost/core/allocator_access.hpp index 5caba94..1fee1e6 100644 --- a/include/boost/core/allocator_access.hpp +++ b/include/boost/core/allocator_access.hpp @@ -47,7 +47,7 @@ namespace detail { template struct alloc_ptr { - typedef typename allocator_value_type::type* type; + typedef typename boost::allocator_value_type::type* type; }; template @@ -80,8 +80,8 @@ namespace detail { template struct alloc_const_ptr { typedef typename boost::pointer_traits::type>::template - rebind_to::type type; + boost::allocator_pointer::type>::template rebind_to::type>::type type; }; template @@ -399,8 +399,9 @@ template class alloc_has_allocate { template static auto check(int) -> decltype(std::declval().allocate( - std::declval::type>(), - std::declval::type>())); + std::declval::type>(), + std::declval::type>())); template static alloc_none check(long); From 0c9675cf56553f83577e315c6625a8e7c2c7c13d Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Mon, 6 Dec 2021 16:42:17 -0500 Subject: [PATCH 152/258] Add partial C++03 support for C++11 allocator model --- include/boost/core/allocator_access.hpp | 273 ++++++++++++++---------- 1 file changed, 162 insertions(+), 111 deletions(-) diff --git a/include/boost/core/allocator_access.hpp b/include/boost/core/allocator_access.hpp index 1fee1e6..fab7474 100644 --- a/include/boost/core/allocator_access.hpp +++ b/include/boost/core/allocator_access.hpp @@ -9,16 +9,28 @@ Distributed under the Boost Software License, Version 1.0. #define BOOST_CORE_ALLOCATOR_ACCESS_HPP #include -#if !defined(BOOST_NO_CXX11_ALLOCATOR) #include #include +#include +#if !defined(BOOST_NO_CXX11_ALLOCATOR) #include #endif -#include #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) #include #endif +#if defined(BOOST_GCC_VERSION) && (BOOST_GCC_VERSION >= 40300) +#define BOOST_DETAIL_ALLOC_HAS_IS_EMTPY +#elif defined(BOOST_INTEL) && defined(_MSC_VER) && (_MSC_VER >= 1500) +#define BOOST_DETAIL_ALLOC_HAS_IS_EMTPY +#elif defined(BOOST_MSVC) && (BOOST_MSVC >= 1400) +#define BOOST_DETAIL_ALLOC_HAS_IS_EMTPY +#elif defined(BOOST_CLANG) && !defined(__CUDACC__) +#if __has_feature(is_empty) +#define BOOST_DETAIL_ALLOC_HAS_IS_EMTPY +#endif +#endif + #if defined(_LIBCPP_SUPPRESS_DEPRECATED_PUSH) _LIBCPP_SUPPRESS_DEPRECATED_PUSH #endif @@ -37,12 +49,6 @@ struct allocator_value_type { typedef typename A::value_type type; }; -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_pointer { - typedef typename A::pointer type; -}; -#else namespace detail { template @@ -67,14 +73,7 @@ template struct allocator_pointer { typedef typename detail::alloc_ptr::type type; }; -#endif -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_const_pointer { - typedef typename A::const_pointer type; -}; -#else namespace detail { template @@ -96,23 +95,34 @@ template struct allocator_const_pointer { typedef typename detail::alloc_const_ptr::type type; }; -#endif -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_rebind { - typedef typename A::template rebind::other type; -}; -#else namespace detail { template struct alloc_to { }; +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +template class A, class T, class U> +struct alloc_to, T> { + typedef A type; +}; + +template class A, class T, class U, class V> +struct alloc_to, T> { + typedef A type; +}; + +template class A, class T, class U, class V1, + class V2> +struct alloc_to, T> { + typedef A type; +}; +#else template class A, class T, class U, class... V> struct alloc_to, T> { typedef A type; }; +#endif template struct alloc_rebind { @@ -131,15 +141,7 @@ template struct allocator_rebind { typedef typename detail::alloc_rebind::type type; }; -#endif -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_void_pointer { - typedef typename allocator_pointer::type>::type type; -}; -#else namespace detail { template @@ -161,15 +163,7 @@ template struct allocator_void_pointer { typedef typename detail::alloc_void_ptr::type type; }; -#endif -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_const_void_pointer { - typedef typename allocator_const_pointer::type>::type type; -}; -#else namespace detail { template @@ -191,14 +185,7 @@ template struct allocator_const_void_pointer { typedef typename detail::alloc_const_void_ptr::type type; }; -#endif -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_difference_type { - typedef typename A::difference_type type; -}; -#else namespace detail { template @@ -219,21 +206,21 @@ template struct allocator_difference_type { typedef typename detail::alloc_diff_type::type type; }; -#endif -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_size_type { - typedef typename A::size_type type; -}; -#else namespace detail { +#if defined(BOOST_NO_CXX11_ALLOCATOR) +template +struct alloc_size_type { + typedef std::size_t type; +}; +#else template struct alloc_size_type { typedef typename std::make_unsigned::type>::type type; }; +#endif template struct alloc_size_type struct allocator_size_type { typedef typename detail::alloc_size_type::type type; }; -#endif + +namespace detail { #if defined(BOOST_NO_CXX11_ALLOCATOR) -namespace detail { +template +struct alloc_bool { + typedef bool value_type; + typedef alloc_bool type; -struct alloc_false { - BOOST_STATIC_CONSTEXPR bool value = false; + static const bool value = V; + + operator bool() const BOOST_NOEXCEPT { + return V; + } + + bool operator()() const BOOST_NOEXCEPT { + return V; + } }; -} /* detail */ +template +const bool alloc_bool::value; -template -struct allocator_propagate_on_container_copy_assignment { - typedef detail::alloc_false type; -}; +typedef alloc_bool alloc_false; #else -namespace detail { +typedef std::false_type alloc_false; +#endif template struct alloc_pocca { - typedef std::false_type type; + typedef alloc_false type; }; template @@ -283,19 +280,12 @@ template struct allocator_propagate_on_container_copy_assignment { typedef typename detail::alloc_pocca::type type; }; -#endif -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_propagate_on_container_move_assignment { - typedef detail::alloc_false type; -}; -#else namespace detail { template struct alloc_pocma { - typedef std::false_type type; + typedef alloc_false type; }; template @@ -311,19 +301,12 @@ template struct allocator_propagate_on_container_move_assignment { typedef typename detail::alloc_pocma::type type; }; -#endif -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_propagate_on_container_swap { - typedef detail::alloc_false type; -}; -#else namespace detail { template struct alloc_pocs { - typedef std::false_type type; + typedef alloc_false type; }; template @@ -338,20 +321,25 @@ template struct allocator_propagate_on_container_swap { typedef typename detail::alloc_pocs::type type; }; -#endif -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_is_always_equal { - typedef detail::alloc_false type; -}; -#else namespace detail { +#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct alloc_equal { typedef typename std::is_empty::type type; }; +#elif defined(BOOST_DETAIL_ALLOC_HAS_IS_EMTPY) +template +struct alloc_equal { + typedef alloc_bool<__is_empty(A)> type; +}; +#else +template +struct alloc_equal { + typedef alloc_false type; +}; +#endif template struct alloc_equal struct allocator_is_always_equal { typedef typename detail::alloc_equal::type type; }; -#endif template inline typename allocator_pointer::type @@ -551,20 +538,46 @@ allocator_destroy(A&, T* p) } #endif -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -inline typename allocator_size_type::type -allocator_max_size(const A& a) BOOST_NOEXCEPT -{ - return a.max_size(); -} -#else namespace detail { +#if defined(BOOST_NO_CXX11_ALLOCATOR) +template::type(A::*)()> +struct alloc_max_size { + char one, two; +}; + +template::type(A::*)() const> +struct alloc_max_size_const { + char one, two; +}; + +template::type(*)()> +struct alloc_max_size_static { + char one, two; +}; + template class alloc_has_max_size { template - static auto check(int) -> decltype(std::declval().max_size()); + static alloc_max_size check(int); + + template + static alloc_max_size_const check(int); + + template + static alloc_max_size_static check(int); + + template + static char check(long); + +public: + BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) != 1; +}; +#else +template +class alloc_has_max_size { + template + static auto check(int) -> decltype(std::declval().max_size()); template static alloc_none check(long); @@ -573,11 +586,20 @@ public: BOOST_STATIC_CONSTEXPR bool value = !std::is_same(0)), alloc_none>::value; }; +#endif + +template +struct alloc_if { }; + +template +struct alloc_if { + typedef T type; +}; } /* detail */ template -inline typename std::enable_if::value, +inline typename detail::alloc_if::value, typename allocator_size_type::type>::type allocator_max_size(const A& a) BOOST_NOEXCEPT { @@ -585,7 +607,7 @@ allocator_max_size(const A& a) BOOST_NOEXCEPT } template -inline typename std::enable_if::value, +inline typename detail::alloc_if::value, typename allocator_size_type::type>::type allocator_max_size(const A&) BOOST_NOEXCEPT { @@ -593,23 +615,52 @@ allocator_max_size(const A&) BOOST_NOEXCEPT allocator_size_type::type>::max)() / sizeof(typename allocator_value_type::type); } -#endif + +namespace detail { #if defined(BOOST_NO_CXX11_ALLOCATOR) -template -inline A -allocator_select_on_container_copy_construction(const A& a) -{ - return a; -} -#else -namespace detail { +template +struct alloc_soccc { + char one, two; +}; + +template +struct alloc_soccc_const { + char one, two; +}; + +template +struct alloc_soccc_static { + char one, two; +}; +template +class alloc_has_soccc { + template + static alloc_soccc + check(int); + + template + static alloc_soccc_const + check(int); + + template + static alloc_soccc_static + check(int); + + template + static char check(long); + +public: + BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) != 1; +}; +#else template class alloc_has_soccc { template static auto check(int) - -> decltype(std::declval().select_on_container_copy_construction()); + -> decltype(std::declval().select_on_container_copy_construction()); template static alloc_none check(long); @@ -618,23 +669,23 @@ public: BOOST_STATIC_CONSTEXPR bool value = !std::is_same(0)), alloc_none>::value; }; +#endif } /* detail */ template -inline typename std::enable_if::value, A>::type +inline typename detail::alloc_if::value, A>::type allocator_select_on_container_copy_construction(const A& a) { return a.select_on_container_copy_construction(); } template -inline typename std::enable_if::value, A>::type +inline typename detail::alloc_if::value, A>::type allocator_select_on_container_copy_construction(const A& a) { return a; } -#endif #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) template From 85a3183c01e2ceb2d98f026b8e1d0f3f601d9829 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Mon, 6 Dec 2021 23:25:32 -0500 Subject: [PATCH 153/258] Update bool constant --- include/boost/core/allocator_access.hpp | 2 +- include/boost/core/default_allocator.hpp | 22 +++++++++++++--------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/include/boost/core/allocator_access.hpp b/include/boost/core/allocator_access.hpp index fab7474..9dc4017 100644 --- a/include/boost/core/allocator_access.hpp +++ b/include/boost/core/allocator_access.hpp @@ -241,7 +241,7 @@ namespace detail { template struct alloc_bool { typedef bool value_type; - typedef alloc_bool type; + typedef alloc_bool type; static const bool value = V; diff --git a/include/boost/core/default_allocator.hpp b/include/boost/core/default_allocator.hpp index ba8540b..91d3bbc 100644 --- a/include/boost/core/default_allocator.hpp +++ b/include/boost/core/default_allocator.hpp @@ -19,21 +19,25 @@ BOOST_NORETURN void throw_exception(const std::exception&); namespace default_ { -struct true_type { +template +struct bool_constant { typedef bool value_type; - typedef true_type type; + typedef bool_constant type; - BOOST_STATIC_CONSTANT(bool, value = true); + static const bool value = V; - BOOST_CONSTEXPR operator bool() const BOOST_NOEXCEPT { - return true; + operator bool() const BOOST_NOEXCEPT { + return V; } - BOOST_CONSTEXPR bool operator()() const BOOST_NOEXCEPT { - return true; + bool operator()() const BOOST_NOEXCEPT { + return V; } }; +template +const bool bool_constant::value; + template struct add_reference { typedef T& type; @@ -58,8 +62,8 @@ struct default_allocator { typedef typename add_reference::type const_reference; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; - typedef true_type propagate_on_container_move_assignment; - typedef true_type is_always_equal; + typedef bool_constant propagate_on_container_move_assignment; + typedef bool_constant is_always_equal; template struct rebind { From ac4bdcc4c5656f8ce578bf7fd7e2b4f138f472ee Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Mon, 6 Dec 2021 23:43:03 -0500 Subject: [PATCH 154/258] Update documentation --- doc/allocator_access.qbk | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/allocator_access.qbk b/doc/allocator_access.qbk index 6b649e7..08f71e8 100644 --- a/doc/allocator_access.qbk +++ b/doc/allocator_access.qbk @@ -168,7 +168,8 @@ A allocator_select_on_container_copy_construction(const A& a); [[`template struct allocator_value_type;`] [The member `type` is `A::value_type`.]] [[`template struct allocator_pointer;`] -[The member `type` is `A::pointer` if valid, otherwise `A::value_type*`.]] +[The member `type` is `A::pointer` if valid, otherwise +`allocator_value_type_t*`.]] [[`template struct allocator_const_pointer;`] [The member `type` is `A::const_pointer` if valid, otherwise `pointer_traits >::rebind allocator_size_type_t allocator_max_size(const A& a);`] [Returns `a.max_size()` if valid, otherwise returns `std::numeric_limits >::max() / -sizeof(A::value_type)`.]] +sizeof(allocator_value_type_t)`.]] [[`template A allocator_select_on_container_copy_construction(const A& a);`] [Returns `a.select_on_container_copy_construction()` if valid, otherwise From d038633f985af111e7ad0ad539ee8c411c9a918b Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Tue, 7 Dec 2021 02:57:14 -0500 Subject: [PATCH 155/258] Correct spelling of detail macro --- include/boost/core/allocator_access.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/boost/core/allocator_access.hpp b/include/boost/core/allocator_access.hpp index 9dc4017..19a1129 100644 --- a/include/boost/core/allocator_access.hpp +++ b/include/boost/core/allocator_access.hpp @@ -20,14 +20,14 @@ Distributed under the Boost Software License, Version 1.0. #endif #if defined(BOOST_GCC_VERSION) && (BOOST_GCC_VERSION >= 40300) -#define BOOST_DETAIL_ALLOC_HAS_IS_EMTPY +#define BOOST_DETAIL_ALLOC_HAS_IS_EMPTY #elif defined(BOOST_INTEL) && defined(_MSC_VER) && (_MSC_VER >= 1500) -#define BOOST_DETAIL_ALLOC_HAS_IS_EMTPY +#define BOOST_DETAIL_ALLOC_HAS_IS_EMPTY #elif defined(BOOST_MSVC) && (BOOST_MSVC >= 1400) -#define BOOST_DETAIL_ALLOC_HAS_IS_EMTPY +#define BOOST_DETAIL_ALLOC_HAS_IS_EMPTY #elif defined(BOOST_CLANG) && !defined(__CUDACC__) #if __has_feature(is_empty) -#define BOOST_DETAIL_ALLOC_HAS_IS_EMTPY +#define BOOST_DETAIL_ALLOC_HAS_IS_EMPTY #endif #endif @@ -329,7 +329,7 @@ template struct alloc_equal { typedef typename std::is_empty::type type; }; -#elif defined(BOOST_DETAIL_ALLOC_HAS_IS_EMTPY) +#elif defined(BOOST_DETAIL_ALLOC_HAS_IS_EMPTY) template struct alloc_equal { typedef alloc_bool<__is_empty(A)> type; From eb7bc1ff53cc7179e20bab6fefbefc7fb2840660 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Tue, 7 Dec 2021 10:10:07 -0500 Subject: [PATCH 156/258] Support additional is_empty intrinsics --- include/boost/core/allocator_access.hpp | 27 +++++++++++++++---------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/include/boost/core/allocator_access.hpp b/include/boost/core/allocator_access.hpp index 19a1129..6a64c0b 100644 --- a/include/boost/core/allocator_access.hpp +++ b/include/boost/core/allocator_access.hpp @@ -20,15 +20,21 @@ Distributed under the Boost Software License, Version 1.0. #endif #if defined(BOOST_GCC_VERSION) && (BOOST_GCC_VERSION >= 40300) -#define BOOST_DETAIL_ALLOC_HAS_IS_EMPTY +#define BOOST_DETAIL_ALLOC_EMPTY(T) __is_empty(T) #elif defined(BOOST_INTEL) && defined(_MSC_VER) && (_MSC_VER >= 1500) -#define BOOST_DETAIL_ALLOC_HAS_IS_EMPTY +#define BOOST_DETAIL_ALLOC_EMPTY(T) __is_empty(T) #elif defined(BOOST_MSVC) && (BOOST_MSVC >= 1400) -#define BOOST_DETAIL_ALLOC_HAS_IS_EMPTY +#define BOOST_DETAIL_ALLOC_EMPTY(T) __is_empty(T) #elif defined(BOOST_CLANG) && !defined(__CUDACC__) #if __has_feature(is_empty) -#define BOOST_DETAIL_ALLOC_HAS_IS_EMPTY +#define BOOST_DETAIL_ALLOC_EMPTY(T) __is_empty(T) #endif +#elif defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5130) +#define BOOST_DETAIL_ALLOC_EMPTY(T) __oracle_is_empty(T) +#elif defined(__ghs__) && (__GHS_VERSION_NUMBER >= 600) +#define BOOST_DETAIL_ALLOC_EMPTY(T) __is_empty(T) +#elif defined(BOOST_CODEGEARC) +#define BOOST_DETAIL_ALLOC_EMPTY(T) __is_empty(T) #endif #if defined(_LIBCPP_SUPPRESS_DEPRECATED_PUSH) @@ -329,10 +335,10 @@ template struct alloc_equal { typedef typename std::is_empty::type type; }; -#elif defined(BOOST_DETAIL_ALLOC_HAS_IS_EMPTY) +#elif defined(BOOST_DETAIL_ALLOC_EMPTY) template struct alloc_equal { - typedef alloc_bool<__is_empty(A)> type; + typedef alloc_bool type; }; #else template @@ -385,9 +391,9 @@ struct alloc_none { }; template class alloc_has_allocate { template - static auto check(int) -> decltype(std::declval().allocate( - std::declval::type>(), - std::declval decltype(std::declval().allocate(std::declval::type>(), std::declval::type>())); template @@ -658,8 +664,7 @@ public: template class alloc_has_soccc { template - static auto check(int) - -> decltype(std::declval decltype(std::declval().select_on_container_copy_construction()); template From c8479b4eca146ea01717b3be3020cc6c21c66f63 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Tue, 7 Dec 2021 21:08:04 -0500 Subject: [PATCH 157/258] Simplify C++03 detection traits slightly --- include/boost/core/allocator_access.hpp | 47 +++++++------------------ 1 file changed, 13 insertions(+), 34 deletions(-) diff --git a/include/boost/core/allocator_access.hpp b/include/boost/core/allocator_access.hpp index 6a64c0b..ab5363a 100644 --- a/include/boost/core/allocator_access.hpp +++ b/include/boost/core/allocator_access.hpp @@ -547,31 +547,25 @@ allocator_destroy(A&, T* p) namespace detail { #if defined(BOOST_NO_CXX11_ALLOCATOR) -template::type(A::*)()> -struct alloc_max_size { - char one, two; -}; - -template::type(A::*)() const> -struct alloc_max_size_const { - char one, two; -}; - -template::type(*)()> -struct alloc_max_size_static { - char one, two; +template +struct alloc_no { + char x; + char y; }; template class alloc_has_max_size { template - static alloc_max_size check(int); + static alloc_no::type(O::*)(), + &O::max_size> check(int); template - static alloc_max_size_const check(int); + static alloc_no::type(O::*)() const, + &O::max_size> check(int); template - static alloc_max_size_static check(int); + static alloc_no::type(*)(), + &O::max_size> check(int); template static char check(long); @@ -625,33 +619,18 @@ allocator_max_size(const A&) BOOST_NOEXCEPT namespace detail { #if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct alloc_soccc { - char one, two; -}; - -template -struct alloc_soccc_const { - char one, two; -}; - -template -struct alloc_soccc_static { - char one, two; -}; - template class alloc_has_soccc { template - static alloc_soccc + static alloc_no check(int); template - static alloc_soccc_const + static alloc_no check(int); template - static alloc_soccc_static + static alloc_no check(int); template From 6da7958281fcdbd8fa768e37686c62984c8af673 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Wed, 8 Dec 2021 10:26:49 -0500 Subject: [PATCH 158/258] Update unit tests --- test/allocator_const_pointer_test.cpp | 4 ---- test/allocator_const_void_pointer_test.cpp | 4 ---- test/allocator_difference_type_test.cpp | 4 ---- test/allocator_is_always_equal_test.cpp | 12 ++++++------ test/allocator_max_size_test.cpp | 4 ---- test/allocator_pocca_test.cpp | 8 +++----- test/allocator_pocma_test.cpp | 8 +++----- test/allocator_pocs_test.cpp | 8 +++----- test/allocator_pointer_test.cpp | 4 ---- test/allocator_rebind_test.cpp | 4 ---- test/allocator_soccc_test.cpp | 4 ---- test/allocator_void_pointer_test.cpp | 4 ---- 12 files changed, 15 insertions(+), 53 deletions(-) diff --git a/test/allocator_const_pointer_test.cpp b/test/allocator_const_pointer_test.cpp index 16ae707..fb83627 100644 --- a/test/allocator_const_pointer_test.cpp +++ b/test/allocator_const_pointer_test.cpp @@ -15,20 +15,16 @@ struct A1 { typedef int* const_pointer; }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct A2 { typedef T value_type; }; -#endif int main() { BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); -#endif return boost::report_errors(); } diff --git a/test/allocator_const_void_pointer_test.cpp b/test/allocator_const_void_pointer_test.cpp index c07070d..9f8610c 100644 --- a/test/allocator_const_void_pointer_test.cpp +++ b/test/allocator_const_void_pointer_test.cpp @@ -20,20 +20,16 @@ struct A1 { }; }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct A2 { typedef T value_type; }; -#endif int main() { BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); -#endif return boost::report_errors(); } diff --git a/test/allocator_difference_type_test.cpp b/test/allocator_difference_type_test.cpp index 24c373d..c0c0316 100644 --- a/test/allocator_difference_type_test.cpp +++ b/test/allocator_difference_type_test.cpp @@ -15,20 +15,16 @@ struct A1 { typedef short difference_type; }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct A2 { typedef T value_type; }; -#endif int main() { BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); -#endif return boost::report_errors(); } diff --git a/test/allocator_is_always_equal_test.cpp b/test/allocator_is_always_equal_test.cpp index c0d8bf2..fd2c03e 100644 --- a/test/allocator_is_always_equal_test.cpp +++ b/test/allocator_is_always_equal_test.cpp @@ -15,7 +15,6 @@ struct A1 { int value; }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct A2 { typedef T value_type; @@ -24,24 +23,25 @@ struct A2 { template struct A3 { typedef T value_type; - typedef std::false_type is_always_equal; + struct is_always_equal { + static const bool value = false; + }; }; template struct A4 { typedef T value_type; - typedef std::true_type is_always_equal; + struct is_always_equal { + static const bool value = true; + }; int value; }; -#endif int main() { BOOST_TEST_TRAIT_FALSE((boost::allocator_is_always_equal >::type)); - #if !defined(BOOST_NO_CXX11_ALLOCATOR) BOOST_TEST_TRAIT_TRUE((boost::allocator_is_always_equal >::type)); BOOST_TEST_TRAIT_FALSE((boost::allocator_is_always_equal >::type)); BOOST_TEST_TRAIT_TRUE((boost::allocator_is_always_equal >::type)); - #endif return boost::report_errors(); } diff --git a/test/allocator_max_size_test.cpp b/test/allocator_max_size_test.cpp index 7da57d6..b2837f1 100644 --- a/test/allocator_max_size_test.cpp +++ b/test/allocator_max_size_test.cpp @@ -19,21 +19,17 @@ struct A1 { } }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct A2 { typedef T value_type; typedef short size_type; A2() { } }; -#endif int main() { BOOST_TEST_EQ(boost::allocator_max_size(A1()), 1); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) BOOST_TEST_LE(boost::allocator_max_size(A2()), (std::numeric_limits::max)()); -#endif return boost::report_errors(); } diff --git a/test/allocator_pocca_test.cpp b/test/allocator_pocca_test.cpp index 2318652..853473a 100644 --- a/test/allocator_pocca_test.cpp +++ b/test/allocator_pocca_test.cpp @@ -14,21 +14,19 @@ struct A1 { typedef T value_type; }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct A2 { typedef T value_type; - typedef std::true_type propagate_on_container_copy_assignment; + struct propagate_on_container_copy_assignment { + static const bool value = true; + }; }; -#endif int main() { BOOST_TEST_TRAIT_FALSE((boost:: allocator_propagate_on_container_copy_assignment >::type)); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) BOOST_TEST_TRAIT_TRUE((boost:: allocator_propagate_on_container_copy_assignment >::type)); -#endif return boost::report_errors(); } diff --git a/test/allocator_pocma_test.cpp b/test/allocator_pocma_test.cpp index a971c02..6c0c8e3 100644 --- a/test/allocator_pocma_test.cpp +++ b/test/allocator_pocma_test.cpp @@ -14,21 +14,19 @@ struct A1 { typedef T value_type; }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct A2 { typedef T value_type; - typedef std::true_type propagate_on_container_move_assignment; + struct propagate_on_container_move_assignment { + static const bool value = true; + }; }; -#endif int main() { BOOST_TEST_TRAIT_FALSE((boost:: allocator_propagate_on_container_move_assignment >::type)); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) BOOST_TEST_TRAIT_TRUE((boost:: allocator_propagate_on_container_move_assignment >::type)); -#endif return boost::report_errors(); } diff --git a/test/allocator_pocs_test.cpp b/test/allocator_pocs_test.cpp index 1a8e6e2..2f90f3f 100644 --- a/test/allocator_pocs_test.cpp +++ b/test/allocator_pocs_test.cpp @@ -14,21 +14,19 @@ struct A1 { typedef T value_type; }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct A2 { typedef T value_type; - typedef std::true_type propagate_on_container_swap; + struct propagate_on_container_swap { + static const bool value = true; + }; }; -#endif int main() { BOOST_TEST_TRAIT_FALSE((boost:: allocator_propagate_on_container_swap >::type)); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) BOOST_TEST_TRAIT_TRUE((boost:: allocator_propagate_on_container_swap >::type)); -#endif return boost::report_errors(); } diff --git a/test/allocator_pointer_test.cpp b/test/allocator_pointer_test.cpp index 6359492..6ff445e 100644 --- a/test/allocator_pointer_test.cpp +++ b/test/allocator_pointer_test.cpp @@ -15,20 +15,16 @@ struct A1 { typedef int* pointer; }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct A2 { typedef T value_type; }; -#endif int main() { BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); -#endif return boost::report_errors(); } diff --git a/test/allocator_rebind_test.cpp b/test/allocator_rebind_test.cpp index 4e35da4..88015f2 100644 --- a/test/allocator_rebind_test.cpp +++ b/test/allocator_rebind_test.cpp @@ -18,20 +18,16 @@ struct A1 { }; }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct A2 { typedef T value_type; }; -#endif int main() { BOOST_TEST_TRAIT_TRUE((boost::core::is_same, boost::allocator_rebind, bool>::type>)); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) BOOST_TEST_TRAIT_TRUE((boost::core::is_same, boost::allocator_rebind, int>::type>)); -#endif return boost::report_errors(); } diff --git a/test/allocator_soccc_test.cpp b/test/allocator_soccc_test.cpp index 2d25fbd..7f65233 100644 --- a/test/allocator_soccc_test.cpp +++ b/test/allocator_soccc_test.cpp @@ -16,7 +16,6 @@ struct A1 { int value; }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct A2 { typedef T value_type; @@ -27,15 +26,12 @@ struct A2 { } int value; }; -#endif int main() { BOOST_TEST_EQ(1, boost:: allocator_select_on_container_copy_construction(A1(1)).value); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) BOOST_TEST_EQ(2, boost:: allocator_select_on_container_copy_construction(A2(1)).value); -#endif return boost::report_errors(); } diff --git a/test/allocator_void_pointer_test.cpp b/test/allocator_void_pointer_test.cpp index c5c08c1..d7133be 100644 --- a/test/allocator_void_pointer_test.cpp +++ b/test/allocator_void_pointer_test.cpp @@ -20,20 +20,16 @@ struct A1 { }; }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct A2 { typedef T value_type; }; -#endif int main() { BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); -#endif return boost::report_errors(); } From 0e62373aa247bf321393c4550e842882ab81fed0 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Sun, 12 Dec 2021 19:03:57 -0500 Subject: [PATCH 159/258] Make pointer_traits SFINAE friendly --- doc/pointer_traits.qbk | 67 +++++--- include/boost/core/pointer_traits.hpp | 146 ++++++++++-------- test/Jamfile.v2 | 3 + .../pointer_traits_pointer_to_sfinae_test.cpp | 75 +++++++++ test/pointer_traits_rebind_sfinae_test.cpp | 83 ++++++++++ test/pointer_traits_sfinae_test.cpp | 101 ++++++++++++ test/to_address_test.cpp | 72 ++------- 7 files changed, 397 insertions(+), 150 deletions(-) create mode 100644 test/pointer_traits_pointer_to_sfinae_test.cpp create mode 100644 test/pointer_traits_rebind_sfinae_test.cpp create mode 100644 test/pointer_traits_sfinae_test.cpp diff --git a/doc/pointer_traits.qbk b/doc/pointer_traits.qbk index d0247fa..716d815 100644 --- a/doc/pointer_traits.qbk +++ b/doc/pointer_traits.qbk @@ -1,5 +1,5 @@ [/ -Copyright 2017-2018 Glen Joseph Fernandes +Copyright 2017-2021 Glen Joseph Fernandes (glenjofe@gmail.com) Distributed under the Boost Software License, Version 1.0. @@ -47,68 +47,87 @@ void function(Allocator& a) ``` namespace boost { - template struct pointer_traits { + +template +struct pointer_traits { typedef T pointer; typedef ``['see below]`` element_type; typedef ``['see below]`` difference_type; - template struct rebind_to { typedef ``['see below]`` type; }; - template using rebind = typename rebind_to::type; + template + struct rebind_to { + typedef ``['see below]`` type; + }; - static pointer pointer_to(``['see below]`` v); - }; + template + using rebind = typename rebind_to::type; - template struct pointer_traits { + static pointer pointer_to(element_type& v); +}; + +template +struct pointer_traits { typedef T* pointer; typedef T element_type; typedef std::ptrdiff_t difference_type; - template struct rebind_to { typedef U* type; }; - template using rebind = typename rebind_to::type; + template + struct rebind_to { + typedef U* type; + }; + + template + using rebind = typename rebind_to::type; static pointer pointer_to(``['see below]`` v) noexcept; - }; +}; - template - constexpr T* to_address(T* v) noexcept; +template +constexpr T* to_address(T* v) noexcept; - template - auto to_address(const T& v) noexcept; -} +template +auto to_address(const T& v) noexcept; + +} // boost ``` +[section Overview] + +If the member type `element_type` is not defined, then all other members are +also not defined (`pointer_traits` is SFINAE-friendly). + +[endsect] + [section Member types] [variablelist [[`typedef` ['see below] `element_type;`] [`T::element_type` if such a type exists; otherwise `U` if `T` is a class template instantiation of the form `Pointer`, where `Args` is zero - or more type arguments; otherwise the specialization is ill-formed.]] + or more type arguments; otherwise the member is not defined.]] [[`typedef` ['see below] `difference_type;`] [`T::difference_type` if such a type exists; otherwise `std::ptrdiff_t`.]] [[`template struct rebind_to { typedef` ['see below] `type; };`] [`type` is `T::rebind` if such a type exists; otherwise, `Pointer` if `T` is a class template instantiation of the form `Pointer`, - where `Args` is zero or more type arguments; otherwise, the instantiation of - `rebind_to` is ill-formed.]]] + where `Args` is zero or more type arguments; otherwise, the member is not + defined.]]] [endsect] [section Member functions] [variablelist -[[`static pointer pointer_traits::pointer_to(`['see below] `v);`] +[[`static pointer pointer_traits::pointer_to(element_type& v);`] [[variablelist [[Remark] -[If `element_type` is a void type, the type of `v` is unspecified; otherwise, - it is `element_type&`.]] +[If `element_type` is a void type, this member is not defined.]] [[Returns] [A pointer to `v` obtained by calling `T::pointer_to(v)`.]]]]] -[[`static pointer pointer_traits::pointer_to(`['see below] `v) noexcept;`] +[[`static pointer pointer_traits::pointer_to(element_type& v) noexcept;`] [[variablelist [[Remark] -[If `element_type` is a void type, the type of `v` is unspecified; otherwise, - it is `element_type&`.]] +[If `element_type` is a void type, this member is not defined.]] [[Returns][`addressof(v)`.]]]]]] [endsect] diff --git a/include/boost/core/pointer_traits.hpp b/include/boost/core/pointer_traits.hpp index e66194d..2e78598 100644 --- a/include/boost/core/pointer_traits.hpp +++ b/include/boost/core/pointer_traits.hpp @@ -1,5 +1,5 @@ /* -Copyright 2017-2018 Glen Joseph Fernandes +Copyright 2017-2021 Glen Joseph Fernandes (glenjofe@gmail.com) Distributed under the Boost Software License, Version 1.0. @@ -9,43 +9,23 @@ Distributed under the Boost Software License, Version 1.0. #define BOOST_CORE_POINTER_TRAITS_HPP #include -#if !defined(BOOST_NO_CXX11_POINTER_TRAITS) -#include -#else #include #include -#endif namespace boost { - -#if !defined(BOOST_NO_CXX11_POINTER_TRAITS) -template -struct pointer_traits - : std::pointer_traits { - template - struct rebind_to { - typedef typename std::pointer_traits::template rebind type; - }; -}; - -template -struct pointer_traits - : std::pointer_traits { - template - struct rebind_to { - typedef U* type; - }; -}; -#else namespace detail { +struct ptr_none { }; + template -struct ptr_void { +struct ptr_valid { typedef void type; }; -template -struct ptr_first; +template +struct ptr_first { + typedef ptr_none type; +}; #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) template class T, class U, class... Args> @@ -75,7 +55,7 @@ struct ptr_element { }; template -struct ptr_element::type> { +struct ptr_element::type> { typedef typename T::element_type type; }; @@ -86,12 +66,12 @@ struct ptr_difference { template struct ptr_difference::type> { + typename ptr_valid::type> { typedef typename T::difference_type type; }; -template -struct ptr_transform; +template +struct ptr_transform { }; #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) template class T, class U, class... Args, class V> @@ -117,68 +97,100 @@ struct ptr_transform, V> { #endif template -struct ptr_rebind { - typedef typename ptr_transform::type type; -}; +struct ptr_rebind + : ptr_transform { }; -#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) template struct ptr_rebind >::type> { + typename ptr_valid >::type> { typedef typename T::template rebind type; }; -#endif -template -struct ptr_value { - typedef T type; +template +struct ptr_void { + BOOST_STATIC_CONSTEXPR bool value = false; }; template<> -struct ptr_value { - typedef struct { } type; +struct ptr_void { + BOOST_STATIC_CONSTEXPR bool value = true; }; +template<> +struct ptr_void { + BOOST_STATIC_CONSTEXPR bool value = true; +}; + +template<> +struct ptr_void { + BOOST_STATIC_CONSTEXPR bool value = true; +}; + +template<> +struct ptr_void { + BOOST_STATIC_CONSTEXPR bool value = true; +}; + +template::value> +struct ptr_to { }; + +template +struct ptr_to { + static T pointer_to(E& v) { + return T::pointer_to(v); + } +}; + +template +struct ptr_to { + static T* pointer_to(T& v) BOOST_NOEXCEPT { + return boost::addressof(v); + } +}; + +template +struct ptr_traits + : ptr_to { + typedef T pointer; + typedef E element_type; + typedef typename ptr_difference::type difference_type; + + template + struct rebind_to + : ptr_rebind { }; + +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + template + using rebind = typename rebind_to::type; +#endif +}; + +template +struct ptr_traits { }; + } /* detail */ template -struct pointer_traits { - typedef T pointer; - typedef typename detail::ptr_element::type element_type; - typedef typename detail::ptr_difference::type difference_type; - template - struct rebind_to { - typedef typename detail::ptr_rebind::type type; - }; -#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) - template - using rebind = typename detail::ptr_rebind::type; -#endif - static pointer - pointer_to(typename detail::ptr_value::type& v) { - return pointer::pointer_to(v); - } -}; +struct pointer_traits + : detail::ptr_traits::type> { }; template -struct pointer_traits { +struct pointer_traits + : detail::ptr_to { typedef T* pointer; typedef T element_type; typedef std::ptrdiff_t difference_type; + template struct rebind_to { typedef U* type; }; + #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) template - using rebind = U*; + using rebind = typename rebind_to::type*; #endif - static T* - pointer_to(typename detail::ptr_value::type& v) BOOST_NOEXCEPT { - return boost::addressof(v); - } }; -#endif template BOOST_CONSTEXPR inline T* diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 58d46f5..9be78c0 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -189,6 +189,9 @@ run pointer_traits_element_type_test.cpp ; run pointer_traits_difference_type_test.cpp ; run pointer_traits_rebind_test.cpp ; run pointer_traits_pointer_to_test.cpp ; +run pointer_traits_sfinae_test.cpp ; +run pointer_traits_rebind_sfinae_test.cpp ; +run pointer_traits_pointer_to_sfinae_test.cpp ; run to_address_test.cpp ; run exchange_test.cpp ; diff --git a/test/pointer_traits_pointer_to_sfinae_test.cpp b/test/pointer_traits_pointer_to_sfinae_test.cpp new file mode 100644 index 0000000..30f6cec --- /dev/null +++ b/test/pointer_traits_pointer_to_sfinae_test.cpp @@ -0,0 +1,75 @@ +/* +Copyright 2021 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#if !defined(BOOST_NO_CXX11_DECLTYPE_N3276) || !defined(BOOST_MSVC) +#include +#include + +#if !defined(BOOST_NO_CXX11_DECLTYPE_N3276) +template +class has_pointer_to { + template + struct result { + char one; + char two; + }; + + template + static auto check(int) -> result; + + template + static char check(long); + +public: + static const bool value = sizeof(check(0)) != 1; +}; +#else +template +class has_pointer_to { + template + struct result { + char one; + char two; + }; + + template + static result check(int); + + template + static char check(long); + +public: + static const bool value = sizeof(check(0)) != 1; +}; +#endif + +struct P1 { }; + +struct P2 { + typedef int element_type; +}; + +struct P3 { + typedef void element_type; +}; + +int main() +{ + BOOST_TEST((!has_pointer_to >::value)); + BOOST_TEST(has_pointer_to >::value); + BOOST_TEST(!has_pointer_to >::value); + BOOST_TEST(has_pointer_to >::value); + BOOST_TEST(!has_pointer_to >::value); + return boost::report_errors(); +} +#else +int main() +{ + return 0; +} +#endif diff --git a/test/pointer_traits_rebind_sfinae_test.cpp b/test/pointer_traits_rebind_sfinae_test.cpp new file mode 100644 index 0000000..d6ad087 --- /dev/null +++ b/test/pointer_traits_rebind_sfinae_test.cpp @@ -0,0 +1,83 @@ +/* +Copyright 2021 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && \ + (!defined(BOOST_GCC) || (BOOST_GCC >= 40800)) && \ + (!defined(BOOST_MSVC) || (BOOST_MSVC >= 1900)) +#include +#include + +template +struct valid { + typedef void type; +}; + +#if !defined(BOOST_GCC) || (BOOST_GCC >= 50000) +template +struct has_rebind { + static const bool value = false; +}; + +template +struct has_rebind >::type> { + static const bool value = true; +}; +#else +template class T, class U> +using defer = T; + +template +using rebind = defer; + +template class = rebind, class = void> +struct has_rebind { + static const bool value = false; +}; + +template class R> +struct has_rebind >::type> { + static const bool value = true; +}; +#endif + +struct P1 { }; + +struct P2 { + typedef int element_type; +}; + +struct P3 { + typedef int element_type; + + template + struct rebind { }; +}; + +template +struct S { + typedef T element_type; +}; + +typedef S P4; + +int main() +{ + BOOST_TEST((!has_rebind, char>::value)); + BOOST_TEST((!has_rebind, char>::value)); + BOOST_TEST((has_rebind, char>::value)); + BOOST_TEST((has_rebind, char>::value)); + BOOST_TEST((has_rebind, char>::value)); + return boost::report_errors(); +} +#else +int main() +{ + return 0; +} +#endif diff --git a/test/pointer_traits_sfinae_test.cpp b/test/pointer_traits_sfinae_test.cpp new file mode 100644 index 0000000..a7ae787 --- /dev/null +++ b/test/pointer_traits_sfinae_test.cpp @@ -0,0 +1,101 @@ +/* +Copyright 2021 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include + +template +struct valid { + typedef void type; +}; + +template +struct has_pointer { + static const bool value = false; +}; + +template +struct has_pointer::type> { + static const bool value = true; +}; + +template +struct has_element_type { + static const bool value = false; +}; + +template +struct has_element_type::type> { + static const bool value = true; +}; + +template +struct has_difference_type { + static const bool value = false; +}; + +template +struct has_difference_type::type> { + static const bool value = true; +}; + +template +struct has_rebind_to_type { + static const bool value = false; +}; + +template +struct has_rebind_to_type::type>::type> { + static const bool value = true; +}; + +struct P1 { }; + +struct P2 { + typedef int element_type; +}; + +struct P3 { + typedef int element_type; + + template + struct rebind { }; +}; + +template +struct S { + typedef T element_type; +}; + +typedef S P4; + +int main() +{ + BOOST_TEST(!has_pointer >::value); + BOOST_TEST(!has_element_type >::value); + BOOST_TEST(!has_difference_type >::value); + BOOST_TEST((!has_rebind_to_type, char>::value)); + BOOST_TEST(has_pointer >::value); + BOOST_TEST(has_element_type >::value); + BOOST_TEST(has_difference_type >::value); + BOOST_TEST((!has_rebind_to_type, char>::value)); + BOOST_TEST(has_pointer >::value); + BOOST_TEST(has_element_type >::value); + BOOST_TEST(has_difference_type >::value); + BOOST_TEST((has_rebind_to_type, char>::value)); + BOOST_TEST(has_pointer >::value); + BOOST_TEST(has_element_type >::value); + BOOST_TEST(has_difference_type >::value); + BOOST_TEST((has_rebind_to_type, char>::value)); + BOOST_TEST(has_pointer >::value); + BOOST_TEST(has_element_type >::value); + BOOST_TEST(has_difference_type >::value); + BOOST_TEST((has_rebind_to_type, char>::value)); + return boost::report_errors(); +} diff --git a/test/to_address_test.cpp b/test/to_address_test.cpp index 4c02384..4662e32 100644 --- a/test/to_address_test.cpp +++ b/test/to_address_test.cpp @@ -13,9 +13,11 @@ class P1 { public: explicit P1(T* p) : p_(p) { } + T* operator->() const BOOST_NOEXCEPT { return p_; } + private: T* p_; }; @@ -25,9 +27,11 @@ class P2 { public: explicit P2(T* p) : p_(p) { } + P1 operator->() const BOOST_NOEXCEPT { return p_; } + private: P1 p_; }; @@ -38,20 +42,24 @@ class P3 { public: explicit P3(T* p) : p_(p) { } + T* get() const BOOST_NOEXCEPT { return p_; } + private: T* p_; }; namespace boost { + template struct pointer_traits > { static T* to_address(const P3& p) BOOST_NOEXCEPT { return p.get(); } }; + } /* boost */ template @@ -59,77 +67,29 @@ class P4 { public: explicit P4(T* p) : p_(p) { } + T* operator->() const BOOST_NOEXCEPT { return 0; } + T* get() const BOOST_NOEXCEPT { return p_; } + private: int* p_; }; namespace boost { + template struct pointer_traits > { static T* to_address(const P4& p) BOOST_NOEXCEPT { return p.get(); } }; + } /* boost */ - -#if !defined(BOOST_NO_CXX11_POINTER_TRAITS) -template -class P5 { -public: - explicit P5(T* p) - : p_(p) { } - T* get() const BOOST_NOEXCEPT { - return p_; - } -private: - T* p_; -}; - -namespace std { -template -struct pointer_traits > { - static T* to_address(const P5& p) BOOST_NOEXCEPT { - return p.get(); - } -}; -} /* std */ - -template -class P6 { -public: - explicit P6(T* p) - : p_(p) { } - T* get() const BOOST_NOEXCEPT { - return p_; - } -private: - T* p_; -}; - -namespace boost { -template -struct pointer_traits > { - static T* to_address(const P6& p) BOOST_NOEXCEPT { - return p.get(); - } -}; -} /* boost */ - -namespace std { -template -struct pointer_traits > { - static T* to_address(const P6& /*p*/) BOOST_NOEXCEPT { - return 0; - } -}; -} /* std */ -#endif #endif int main() @@ -147,12 +107,6 @@ int main() BOOST_TEST(boost::to_address(p3) == &i); P4 p4(&i); BOOST_TEST(boost::to_address(p4) == &i); -#if !defined(BOOST_NO_CXX11_POINTER_TRAITS) - P5 p5(&i); - BOOST_TEST(boost::to_address(p5) == &i); - P6 p6(&i); - BOOST_TEST(boost::to_address(p6) == &i); -#endif #endif return boost::report_errors(); } From a121ab02782fc19ecb158dbe0d23ea35b20332fd Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Tue, 14 Dec 2021 07:52:42 -0500 Subject: [PATCH 160/258] Update release notes for 1.79 --- doc/changes.qbk | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/changes.qbk b/doc/changes.qbk index e809ee9..88f0d2b 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -9,6 +9,7 @@ [section Changes in 1.79.0] * Added `boost::allocator_traits`, an implementation of `std::allocator_traits`. +* Made `boost::pointer_traits` SFINAE friendly. [endsect] From 78dd0cce2fa4d17510505e9d6a8ec98add57cae6 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Tue, 14 Dec 2021 23:56:22 -0500 Subject: [PATCH 161/258] Make pointer_to SFINAE friendlier --- include/boost/core/pointer_traits.hpp | 69 ++++++++++++++----- .../pointer_traits_pointer_to_sfinae_test.cpp | 43 ++++++------ 2 files changed, 70 insertions(+), 42 deletions(-) diff --git a/include/boost/core/pointer_traits.hpp b/include/boost/core/pointer_traits.hpp index 2e78598..6dae716 100644 --- a/include/boost/core/pointer_traits.hpp +++ b/include/boost/core/pointer_traits.hpp @@ -106,43 +106,74 @@ struct ptr_rebind type; }; -template -struct ptr_void { +#if !defined(BOOST_NO_CXX11_DECLTYPE_N3276) +template +class ptr_to_expr { + template + struct result { + char x, y; + }; + + static E& source(); + + template + static auto check(int) -> result; + + template + static char check(long); + +public: + BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) != 1; +}; + +template +struct ptr_to_expr { + BOOST_STATIC_CONSTEXPR bool value = true; +}; + +template +struct ptr_has_to { + BOOST_STATIC_CONSTEXPR bool value = ptr_to_expr::value; +}; +#else +template +struct ptr_has_to { + BOOST_STATIC_CONSTEXPR bool value = true; +}; +#endif + +template +struct ptr_has_to { BOOST_STATIC_CONSTEXPR bool value = false; }; -template<> -struct ptr_void { - BOOST_STATIC_CONSTEXPR bool value = true; +template +struct ptr_has_to { + BOOST_STATIC_CONSTEXPR bool value = false; }; -template<> -struct ptr_void { - BOOST_STATIC_CONSTEXPR bool value = true; +template +struct ptr_has_to { + BOOST_STATIC_CONSTEXPR bool value = false; }; -template<> -struct ptr_void { - BOOST_STATIC_CONSTEXPR bool value = true; +template +struct ptr_has_to { + BOOST_STATIC_CONSTEXPR bool value = false; }; -template<> -struct ptr_void { - BOOST_STATIC_CONSTEXPR bool value = true; -}; - -template::value> +template::value> struct ptr_to { }; template -struct ptr_to { +struct ptr_to { static T pointer_to(E& v) { return T::pointer_to(v); } }; template -struct ptr_to { +struct ptr_to { static T* pointer_to(T& v) BOOST_NOEXCEPT { return boost::addressof(v); } diff --git a/test/pointer_traits_pointer_to_sfinae_test.cpp b/test/pointer_traits_pointer_to_sfinae_test.cpp index 30f6cec..65a0f72 100644 --- a/test/pointer_traits_pointer_to_sfinae_test.cpp +++ b/test/pointer_traits_pointer_to_sfinae_test.cpp @@ -6,17 +6,15 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#if !defined(BOOST_NO_CXX11_DECLTYPE_N3276) || !defined(BOOST_MSVC) +#if !defined(BOOST_NO_CXX11_DECLTYPE_N3276) #include #include -#if !defined(BOOST_NO_CXX11_DECLTYPE_N3276) template class has_pointer_to { template struct result { - char one; - char two; + char x, y; }; template @@ -28,41 +26,40 @@ class has_pointer_to { public: static const bool value = sizeof(check(0)) != 1; }; -#else -template -class has_pointer_to { - template - struct result { - char one; - char two; - }; - - template - static result check(int); - - template - static char check(long); - -public: - static const bool value = sizeof(check(0)) != 1; -}; -#endif struct P1 { }; struct P2 { typedef int element_type; + + static int* pointer_to(int& value) { + return &value; + } }; struct P3 { typedef void element_type; }; +struct P4 { + typedef int element_type; +}; + +struct P5 { + typedef int element_type; + + static int* pointer_to() { + return 0; + } +}; + int main() { BOOST_TEST((!has_pointer_to >::value)); BOOST_TEST(has_pointer_to >::value); BOOST_TEST(!has_pointer_to >::value); + BOOST_TEST(!has_pointer_to >::value); + BOOST_TEST(!has_pointer_to >::value); BOOST_TEST(has_pointer_to >::value); BOOST_TEST(!has_pointer_to >::value); return boost::report_errors(); From a2b37091eb9fd5a3c4f2fa94cca42734a44bc1e0 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Wed, 15 Dec 2021 11:36:02 -0500 Subject: [PATCH 162/258] Update documentation --- doc/pointer_traits.qbk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/pointer_traits.qbk b/doc/pointer_traits.qbk index 716d815..ce0d7b8 100644 --- a/doc/pointer_traits.qbk +++ b/doc/pointer_traits.qbk @@ -121,7 +121,8 @@ also not defined (`pointer_traits` is SFINAE-friendly). [[`static pointer pointer_traits::pointer_to(element_type& v);`] [[variablelist [[Remark] -[If `element_type` is a void type, this member is not defined.]] +[If `element_type` is a void type, or if `T::pointer_to(v)` is not well formed, + this member is not defined.]] [[Returns] [A pointer to `v` obtained by calling `T::pointer_to(v)`.]]]]] [[`static pointer pointer_traits::pointer_to(element_type& v) noexcept;`] From 02b3f91fc3cc482ed89c96b662b37427cda152f1 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Wed, 15 Dec 2021 15:30:42 -0500 Subject: [PATCH 163/258] Use same style of detection in pointer_traits and allocator_traits --- include/boost/core/allocator_access.hpp | 54 +++++++++---------- include/boost/core/pointer_traits.hpp | 2 +- .../pointer_traits_pointer_to_sfinae_test.cpp | 2 +- 3 files changed, 28 insertions(+), 30 deletions(-) diff --git a/include/boost/core/allocator_access.hpp b/include/boost/core/allocator_access.hpp index ab5363a..247ad75 100644 --- a/include/boost/core/allocator_access.hpp +++ b/include/boost/core/allocator_access.hpp @@ -386,22 +386,24 @@ allocator_allocate(A& a, typename allocator_size_type::type n, #else namespace detail { -struct alloc_none { }; +template +struct alloc_no { + char x, y; +}; template class alloc_has_allocate { template static auto check(int) - -> decltype(std::declval().allocate(std::declval alloc_no().allocate(std::declval::type>(), std::declval::type>())); + boost::allocator_const_void_pointer::type>()))>; template - static alloc_none check(long); + static char check(long); public: - BOOST_STATIC_CONSTEXPR bool value = - !std::is_same(0)), alloc_none>::value; + BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) > 1; }; } /* detail */ @@ -471,15 +473,14 @@ template class alloc_has_construct { template static auto check(int) - -> decltype(std::declval().construct(std::declval(), - std::declval()...)); + -> alloc_no().construct(std::declval(), + std::declval()...))>; template - static alloc_none check(long); + static char check(long); public: - BOOST_STATIC_CONSTEXPR bool value = - !std::is_same(0)), alloc_none>::value; + BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) > 1; }; } /* detail */ @@ -516,14 +517,13 @@ template class alloc_has_destroy { template static auto check(int) - -> decltype(std::declval().destroy(std::declval())); + -> alloc_no().destroy(std::declval()))>; template - static alloc_none check(long); + static char check(long); public: - BOOST_STATIC_CONSTEXPR bool value = - !std::is_same(0)), alloc_none>::value; + BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) > 1; }; } /* detail */ @@ -549,8 +549,7 @@ namespace detail { #if defined(BOOST_NO_CXX11_ALLOCATOR) template struct alloc_no { - char x; - char y; + char x, y; }; template @@ -571,20 +570,20 @@ class alloc_has_max_size { static char check(long); public: - BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) != 1; + BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) > 1; }; #else template class alloc_has_max_size { template - static auto check(int) -> decltype(std::declval().max_size()); + static auto check(int) + -> alloc_no().max_size())>; template - static alloc_none check(long); + static char check(long); public: - BOOST_STATIC_CONSTEXPR bool value = - !std::is_same(0)), alloc_none>::value; + BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) > 1; }; #endif @@ -637,21 +636,20 @@ class alloc_has_soccc { static char check(long); public: - BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) != 1; + BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) > 1; }; #else template class alloc_has_soccc { template - static auto check(int) -> decltype(std::declval().select_on_container_copy_construction()); + static auto check(int) -> alloc_no().select_on_container_copy_construction())>; template - static alloc_none check(long); + static char check(long); public: - BOOST_STATIC_CONSTEXPR bool value = - !std::is_same(0)), alloc_none>::value; + BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) > 1; }; #endif diff --git a/include/boost/core/pointer_traits.hpp b/include/boost/core/pointer_traits.hpp index 6dae716..71c9df6 100644 --- a/include/boost/core/pointer_traits.hpp +++ b/include/boost/core/pointer_traits.hpp @@ -123,7 +123,7 @@ class ptr_to_expr { static char check(long); public: - BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) != 1; + BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) > 1; }; template diff --git a/test/pointer_traits_pointer_to_sfinae_test.cpp b/test/pointer_traits_pointer_to_sfinae_test.cpp index 65a0f72..479bfce 100644 --- a/test/pointer_traits_pointer_to_sfinae_test.cpp +++ b/test/pointer_traits_pointer_to_sfinae_test.cpp @@ -24,7 +24,7 @@ class has_pointer_to { static char check(long); public: - static const bool value = sizeof(check(0)) != 1; + static const bool value = sizeof(check(0)) > 1; }; struct P1 { }; From 7a79d17da2fb57ccec1a32c26a9eeaa45a8a098e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 18 Dec 2021 03:28:17 +0200 Subject: [PATCH 164/258] Add conversions from and to boost::string_view --- .github/workflows/ci.yml | 5 ++++ appveyor.yml | 4 ++- include/boost/core/detail/string_view.hpp | 14 ++++++++++ test/CMakeLists.txt | 6 ++++- test/Jamfile.v2 | 1 + test/sv_conversion_test2.cpp | 32 +++++++++++++++++++++++ 6 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 test/sv_conversion_test2.cpp diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f338a8d..08b62e2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -386,6 +386,9 @@ jobs: git submodule init libs/static_assert git submodule init libs/throw_exception git submodule init libs/type_traits + git submodule init libs/utility + git submodule init libs/io + git submodule init libs/preprocessor git submodule update $GIT_ARGS if [ -z "${{matrix.cmake_tests}}" ] then @@ -517,6 +520,8 @@ jobs: git submodule init libs/static_assert git submodule init libs/throw_exception git submodule init libs/type_traits + git submodule init libs/utility + git submodule init libs/io git submodule update --jobs %GIT_FETCH_JOBS% cmd /c bootstrap b2 -d0 headers diff --git a/appveyor.yml b/appveyor.yml index 9e25cde..bcd5cb6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -# Copyright 2016-2019 Peter Dimov +# Copyright 2016-2021 Peter Dimov # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) @@ -77,6 +77,8 @@ install: - git submodule init libs/static_assert - git submodule init libs/throw_exception - git submodule init libs/type_traits + - git submodule init libs/utility + - git submodule init libs/io - git submodule init tools/build - git submodule init tools/boost_install - git submodule update --jobs 4 diff --git a/include/boost/core/detail/string_view.hpp b/include/boost/core/detail/string_view.hpp index 8b13c0f..fedfbc9 100644 --- a/include/boost/core/detail/string_view.hpp +++ b/include/boost/core/detail/string_view.hpp @@ -34,6 +34,9 @@ namespace boost { + +template class basic_string_view; + namespace core { namespace detail @@ -388,6 +391,11 @@ public: #endif + template basic_string_view( boost::basic_string_view > const& str, + typename boost::enable_if >::type* = 0 ) BOOST_NOEXCEPT: p_( str.data() ), n_( str.size() ) + { + } + // BOOST_CONSTEXPR basic_string_view& operator=( basic_string_view const& ) BOOST_NOEXCEPT & = default; // conversions @@ -407,6 +415,12 @@ public: #endif + template operator boost::basic_string_view, std::char_traits >::type> () const BOOST_NOEXCEPT + { + return boost::basic_string_view< Ch, std::char_traits >( data(), size() ); + } + // iterator support BOOST_CONSTEXPR const_iterator begin() const BOOST_NOEXCEPT diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 4f85621..7524ae6 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2018, 2019, 2021 Peter Dimov +# Copyright 2018-2021 Peter Dimov # Distributed under the Boost Software License, Version 1.0. # See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt @@ -23,6 +23,10 @@ set(BOOST_TEST_LINK_LIBRARIES Boost::core Boost::throw_exception) boost_test(TYPE run SOURCES no_exceptions_support_test.cpp) +set(BOOST_TEST_LINK_LIBRARIES Boost::core Boost::utility) + +boost_test(TYPE run SOURCES sv_conversion_test2.cpp) + endif() add_subdirectory(swap) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 9be78c0..2eedc2e 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -305,6 +305,7 @@ run sv_eq_test.cpp ; run sv_lt_test.cpp ; run sv_stream_insert_test.cpp ; run sv_conversion_test.cpp ; +run sv_conversion_test2.cpp : ; run span_test.cpp ; run span_types_test.cpp ; diff --git a/test/sv_conversion_test2.cpp b/test/sv_conversion_test2.cpp new file mode 100644 index 0000000..ee0e196 --- /dev/null +++ b/test/sv_conversion_test2.cpp @@ -0,0 +1,32 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +boost::core::string_view f( boost::core::string_view const& str ) +{ + return str; +} + +int main() +{ + { + std::string s1( "123" ); + std::string s2 = f( s1 ); + + BOOST_TEST_EQ( s1, s2 ); + } + + { + boost::string_view s1( "123" ); + boost::string_view s2 = f( s1 ); + + BOOST_TEST_EQ( s1, s2 ); + } + + return boost::report_errors(); +} From c83e682b7e6f889cf99957bcd67bf6f509f22ed8 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 18 Dec 2021 05:05:36 +0200 Subject: [PATCH 165/258] Update ci.yml --- .github/workflows/ci.yml | 213 ++++++++++++++++++++++++++++++--------- 1 file changed, 167 insertions(+), 46 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 08b62e2..fdc2b26 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -230,10 +230,6 @@ jobs: cxxstd: "03,11,14,17,2a" os: macos-10.15 - - name: CMake tests - cmake_tests: 1 - os: ubuntu-20.04 - timeout-minutes: 120 runs-on: ${{matrix.os}} container: ${{matrix.container}} @@ -388,21 +384,17 @@ jobs: git submodule init libs/type_traits git submodule init libs/utility git submodule init libs/io - git submodule init libs/preprocessor git submodule update $GIT_ARGS - if [ -z "${{matrix.cmake_tests}}" ] + ./bootstrap.sh + ./b2 headers + if [ -n "${{matrix.compiler}}" -o -n "$GCC_TOOLCHAIN_ROOT" ] then - ./bootstrap.sh - ./b2 headers - if [ -n "${{matrix.compiler}}" -o -n "$GCC_TOOLCHAIN_ROOT" ] + echo -n "using ${{matrix.toolset}} : : ${{matrix.compiler}}" > ~/user-config.jam + if [ -n "$GCC_TOOLCHAIN_ROOT" ] then - echo -n "using ${{matrix.toolset}} : : ${{matrix.compiler}}" > ~/user-config.jam - if [ -n "$GCC_TOOLCHAIN_ROOT" ] - then - echo -n " : \"--gcc-toolchain=$GCC_TOOLCHAIN_ROOT\" \"--gcc-toolchain=$GCC_TOOLCHAIN_ROOT\"" >> ~/user-config.jam - fi - echo " ;" >> ~/user-config.jam + echo -n " : \"--gcc-toolchain=$GCC_TOOLCHAIN_ROOT\" \"--gcc-toolchain=$GCC_TOOLCHAIN_ROOT\"" >> ~/user-config.jam fi + echo " ;" >> ~/user-config.jam fi - name: Run tests @@ -436,42 +428,15 @@ jobs: B2_ARGS+=("libs/$LIBRARY/test") ./b2 "${B2_ARGS[@]}" - - name: Run CMake tests - if: matrix.cmake_tests != '' - run: | - cd ../boost-root - mkdir __build_cmake_test__ && cd __build_cmake_test__ - cmake -DBUILD_TESTING=ON -DBOOST_INCLUDE_LIBRARIES=$LIBRARY .. - cmake --build . --target tests - ctest --output-on-failure - - - name: Run CMake subdir tests - if: matrix.cmake_tests != '' - run: | - cd ../boost-root/libs/$LIBRARY/test/cmake_subdir_test - mkdir __build_cmake_subdir_test__ && cd __build_cmake_subdir_test__ - cmake .. - cmake --build . - cmake --build . --target check - - - name: Run CMake install tests - if: matrix.cmake_tests != '' - run: | - cd ../boost-root - mkdir __build_cmake_install_test__ && cd __build_cmake_install_test__ - cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DCMAKE_INSTALL_PREFIX=~/.local .. - cmake --build . --target install - cd ../libs/$LIBRARY/test/cmake_install_test - mkdir __build_cmake_install_test__ && cd __build_cmake_install_test__ - cmake -DCMAKE_INSTALL_PREFIX=~/.local .. - cmake --build . - cmake --build . --target check - windows: strategy: fail-fast: false matrix: include: + - toolset: msvc-14.0 + cxxstd: "14" + addrmd: 32,64 + os: windows-2019 - toolset: msvc-14.1 cxxstd: "14,17,latest" addrmd: 32,64 @@ -531,3 +496,159 @@ jobs: run: | cd ../boost-root b2 -j %NUMBER_OF_PROCESSORS% libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release + + posix-cmake-subdir: + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-18.04 + - os: ubuntu-20.04 + - os: macos-10.15 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v2 + + - name: Install packages + if: matrix.install + run: sudo apt install ${{matrix.install}} + + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + cd .. + git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + + - name: Use library with add_subdirectory + run: | + cd ../boost-root/libs/$LIBRARY/test/cmake_subdir_test + mkdir __build__ && cd __build__ + cmake .. + cmake --build . + ctest --output-on-failure --no-tests=error + + posix-cmake-install: + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-18.04 + - os: ubuntu-20.04 + - os: macos-10.15 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v2 + + - name: Install packages + if: matrix.install + run: sudo apt install ${{matrix.install}} + + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + cd .. + git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + + - name: Configure + run: | + cd ../boost-root + mkdir __build__ && cd __build__ + cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DCMAKE_INSTALL_PREFIX=~/.local .. + + - name: Install + run: | + cd ../boost-root/__build__ + cmake --build . --target install + + - name: Use the installed library + run: | + cd ../boost-root/libs/$LIBRARY/test/cmake_install_test && mkdir __build__ && cd __build__ + cmake -DCMAKE_INSTALL_PREFIX=~/.local .. + cmake --build . + ctest --output-on-failure --no-tests=error + + posix-cmake-test: + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-18.04 + - os: ubuntu-20.04 + - os: macos-10.15 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v2 + + - name: Install packages + if: matrix.install + run: sudo apt install ${{matrix.install}} + + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + cd .. + git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + + - name: Configure + run: | + cd ../boost-root + mkdir __build__ && cd __build__ + cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DBUILD_TESTING=ON .. + + - name: Build tests + run: | + cd ../boost-root/__build__ + cmake --build . --target tests + + - name: Run tests + run: | + cd ../boost-root/__build__ + ctest --output-on-failure --no-tests=error From ac71c55b4e325a88764fc51adc2fa4320f9a5bd7 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 18 Dec 2021 05:07:12 +0200 Subject: [PATCH 166/258] Remove msvc-14.2 from appveyor.yml (in GHA); use clang-win from VS2019 --- appveyor.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index bcd5cb6..b894436 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -29,14 +29,9 @@ environment: # clang-win 32 bit fails to link with "unable to load mspdbcore.dll (error code: 126)" - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 TOOLSET: clang-win ADDRMD: 64 - CXXSTD: 14,17 - - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - TOOLSET: msvc-14.2 - ADDRMD: 32,64 CXXSTD: 14,17,latest - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 @@ -92,4 +87,4 @@ test_script: - PATH=%ADDPATH%%PATH% - if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD% - if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD% - - b2 -j %NUMBER_OF_PROCESSORS% libs/core/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release + - b2 -j %NUMBER_OF_PROCESSORS% libs/core/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release embed-manifest-via=linker From 28d26d13f179c2bad8ab8dc7af5bd476ca2c7fad Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 18 Dec 2021 07:34:16 +0200 Subject: [PATCH 167/258] Add sv_common_reference_test --- test/Jamfile.v2 | 1 + test/sv_common_reference_test.cpp | 48 +++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 test/sv_common_reference_test.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 2eedc2e..fe97758 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -306,6 +306,7 @@ run sv_lt_test.cpp ; run sv_stream_insert_test.cpp ; run sv_conversion_test.cpp ; run sv_conversion_test2.cpp : ; +run sv_common_reference_test.cpp ; run span_test.cpp ; run span_types_test.cpp ; diff --git a/test/sv_common_reference_test.cpp b/test/sv_common_reference_test.cpp new file mode 100644 index 0000000..998e0ae --- /dev/null +++ b/test/sv_common_reference_test.cpp @@ -0,0 +1,48 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include + +#if BOOST_CXX_VERSION < 202000L + +BOOST_PRAGMA_MESSAGE( "Skipping test because BOOST_CXX_VERSION is " BOOST_STRINGIZE(BOOST_CXX_VERSION) ) +int main() {} + +#else + +#include + +#if !defined(__cpp_lib_concepts) + +BOOST_PRAGMA_MESSAGE( "Skipping test because __cpp_lib_concepts is not defined" ) +int main() {} + +#elif __cpp_lib_concepts < 201907L + +BOOST_PRAGMA_MESSAGE( "Skipping test because __cpp_lib_concepts is " BOOST_STRINGIZE(__cpp_lib_concepts) ) +int main() {} + +#else + +#include + +using T = std::common_reference_t< boost::core::string_view&&, std::string& >; + +static_assert( std::common_reference_with< boost::core::string_view&&, std::string& > ); +static_assert( std::common_reference_with< boost::core::wstring_view&&, std::wstring const& > ); + +int main() +{ + BOOST_TEST_TRAIT_SAME( std::common_reference_t< boost::core::string_view&&, std::string& >, boost::core::string_view ); + BOOST_TEST_TRAIT_SAME( std::common_reference_t< boost::core::wstring_view&&, std::wstring const& >, boost::core::wstring_view ); + + return boost::report_errors(); +} + +#endif +#endif From 95f2a76c90d0b0bd660504fd16dd0c2df09442c6 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 18 Dec 2021 07:43:33 +0200 Subject: [PATCH 168/258] Specialize std::basic_common_reference to enable std::common_reference and std::common_reference_with --- include/boost/core/detail/string_view.hpp | 29 +++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/include/boost/core/detail/string_view.hpp b/include/boost/core/detail/string_view.hpp index fedfbc9..c8343c8 100644 --- a/include/boost/core/detail/string_view.hpp +++ b/include/boost/core/detail/string_view.hpp @@ -31,6 +31,10 @@ #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) # include #endif +#if BOOST_CXX_VERSION >= 202000L +# include +# include +#endif namespace boost { @@ -1216,4 +1220,29 @@ typedef basic_string_view u8string_view; } // namespace core } // namespace boost +// std::common_reference support +// needed for iterators that have reference=string_view and value_type=std::string + +#if BOOST_CXX_VERSION >= 202000L && defined(__cpp_lib_concepts) && __cpp_lib_concepts >= 201907L + +template class Q1, template class Q2> +struct std::basic_common_reference< + boost::core::basic_string_view, + std::basic_string, A>, + Q1, Q2> +{ + using type = boost::core::basic_string_view; +}; + +template class Q1, template class Q2> +struct std::basic_common_reference< + std::basic_string, A>, + boost::core::basic_string_view, + Q1, Q2> +{ + using type = boost::core::basic_string_view; +}; + +#endif + #endif // #ifndef BOOST_CORE_STRING_VIEW_HPP_INCLUDED From 6e6af5fc90c5323cbd5a725bbe3cfef6acd91b55 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 18 Dec 2021 18:18:19 +0200 Subject: [PATCH 169/258] Update sv_common_reference_test to check BOOST_NO_CXX20_HDR_CONCEPTS --- test/sv_common_reference_test.cpp | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/test/sv_common_reference_test.cpp b/test/sv_common_reference_test.cpp index 998e0ae..3a0b444 100644 --- a/test/sv_common_reference_test.cpp +++ b/test/sv_common_reference_test.cpp @@ -8,27 +8,14 @@ #include #include -#if BOOST_CXX_VERSION < 202000L +#if defined(BOOST_NO_CXX20_HDR_CONCEPTS) -BOOST_PRAGMA_MESSAGE( "Skipping test because BOOST_CXX_VERSION is " BOOST_STRINGIZE(BOOST_CXX_VERSION) ) -int main() {} - -#else - -#include - -#if !defined(__cpp_lib_concepts) - -BOOST_PRAGMA_MESSAGE( "Skipping test because __cpp_lib_concepts is not defined" ) -int main() {} - -#elif __cpp_lib_concepts < 201907L - -BOOST_PRAGMA_MESSAGE( "Skipping test because __cpp_lib_concepts is " BOOST_STRINGIZE(__cpp_lib_concepts) ) +BOOST_PRAGMA_MESSAGE( "Skipping test because BOOST_NO_CXX20_HDR_CONCEPTS is defined" ) int main() {} #else +#include #include using T = std::common_reference_t< boost::core::string_view&&, std::string& >; @@ -45,4 +32,3 @@ int main() } #endif -#endif From 574c7cf86ef86149dccafc7efda8b0cc28626aec Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 18 Dec 2021 18:39:03 +0200 Subject: [PATCH 170/258] Update string_view.hpp to use BOOST_NO_CXX20_HDR_CONCEPTS --- include/boost/core/detail/string_view.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/boost/core/detail/string_view.hpp b/include/boost/core/detail/string_view.hpp index c8343c8..fa497ed 100644 --- a/include/boost/core/detail/string_view.hpp +++ b/include/boost/core/detail/string_view.hpp @@ -31,9 +31,8 @@ #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) # include #endif -#if BOOST_CXX_VERSION >= 202000L +#if !defined(BOOST_NO_CXX20_HDR_CONCEPTS) // std::common_reference_with # include -# include #endif namespace boost @@ -1223,7 +1222,7 @@ typedef basic_string_view u8string_view; // std::common_reference support // needed for iterators that have reference=string_view and value_type=std::string -#if BOOST_CXX_VERSION >= 202000L && defined(__cpp_lib_concepts) && __cpp_lib_concepts >= 201907L +#if !defined(BOOST_NO_CXX20_HDR_CONCEPTS) template class Q1, template class Q2> struct std::basic_common_reference< From 0b9624d0470cfd9365fe00297310f2ebc9d48cae Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 18 Dec 2021 18:53:42 +0200 Subject: [PATCH 171/258] Add sv_common_reference_test2 --- test/Jamfile.v2 | 1 + test/sv_common_reference_test2.cpp | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 test/sv_common_reference_test2.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index fe97758..3c49583 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -307,6 +307,7 @@ run sv_stream_insert_test.cpp ; run sv_conversion_test.cpp ; run sv_conversion_test2.cpp : ; run sv_common_reference_test.cpp ; +compile sv_common_reference_test2.cpp ; run span_test.cpp ; run span_types_test.cpp ; diff --git a/test/sv_common_reference_test2.cpp b/test/sv_common_reference_test2.cpp new file mode 100644 index 0000000..91e61e0 --- /dev/null +++ b/test/sv_common_reference_test2.cpp @@ -0,0 +1,24 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +#if !defined(__cpp_lib_ranges) + +BOOST_PRAGMA_MESSAGE( "Skipping test because __cpp_lib_ranges is not defined" ) + +#else + +struct Iterator +{ + using value_type = std::string; + boost::core::string_view operator*() const noexcept; +}; + +static_assert( std::indirectly_readable ); + +#endif From 0ef1c06fd8dde504d7394e97071ad6107ee7af21 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 18 Dec 2021 21:59:21 +0200 Subject: [PATCH 172/258] Add cxxstd=20 to msvc-14.2, msvc-14.3 --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fdc2b26..b1f57b4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -442,11 +442,11 @@ jobs: addrmd: 32,64 os: windows-2016 - toolset: msvc-14.2 - cxxstd: "14,17,latest" + cxxstd: "14,17,20,latest" addrmd: 32,64 os: windows-2019 - toolset: msvc-14.3 - cxxstd: "14,17,latest" + cxxstd: "14,17,20,latest" addrmd: 32,64 os: windows-2022 - toolset: gcc From 392cc988dddebf268c98845213f1d8509efe46da Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 20 Dec 2021 01:30:32 +0200 Subject: [PATCH 173/258] Add sv_windows_h_test --- test/Jamfile.v2 | 1 + test/sv_windows_h_test.cpp | 15 +++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 test/sv_windows_h_test.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 3c49583..567fd37 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -308,6 +308,7 @@ run sv_conversion_test.cpp ; run sv_conversion_test2.cpp : ; run sv_common_reference_test.cpp ; compile sv_common_reference_test2.cpp ; +compile sv_windows_h_test.cpp ; run span_test.cpp ; run span_types_test.cpp ; diff --git a/test/sv_windows_h_test.cpp b/test/sv_windows_h_test.cpp new file mode 100644 index 0000000..d22c7fd --- /dev/null +++ b/test/sv_windows_h_test.cpp @@ -0,0 +1,15 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#if !defined(_WIN32) && !defined(__CYGWIN__) + +#include +BOOST_PRAGMA_MESSAGE( "Skipping test because _WIN32 and __CYGWIN__ are not defined" ) + +#else + +#include +#include + +#endif From df3b9827cfc9f38080c8d90af048f1f20c449c36 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 20 Dec 2021 01:35:55 +0200 Subject: [PATCH 174/258] Enclose std::min in parentheses to guard against --- include/boost/core/detail/string_view.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/core/detail/string_view.hpp b/include/boost/core/detail/string_view.hpp index fa497ed..c742198 100644 --- a/include/boost/core/detail/string_view.hpp +++ b/include/boost/core/detail/string_view.hpp @@ -555,7 +555,7 @@ public: boost::throw_exception( std::out_of_range( "basic_string_view::copy" ), BOOST_CURRENT_LOCATION ); } - std::size_t rlen = std::min( n, size() - pos ); + std::size_t rlen = (std::min)( n, size() - pos ); traits_type::copy( s, data() + pos, rlen ); @@ -569,7 +569,7 @@ public: boost::throw_exception( std::out_of_range( "basic_string_view::substr" ), BOOST_CURRENT_LOCATION ); } - std::size_t rlen = std::min( n, size() - pos ); + std::size_t rlen = (std::min)( n, size() - pos ); return basic_string_view( data() + pos, rlen ); } @@ -578,7 +578,7 @@ public: BOOST_CXX14_CONSTEXPR int compare( basic_string_view str ) const BOOST_NOEXCEPT { - std::size_t rlen = std::min( size(), str.size() ); + std::size_t rlen = (std::min)( size(), str.size() ); int cmp = traits_type::compare( data(), str.data(), rlen ); From 65723e0e1f96d23a230ac9c6222f85baea0d16f6 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Thu, 23 Dec 2021 14:50:35 +0300 Subject: [PATCH 175/258] Added clang-13 CI jobs. --- .github/workflows/ci.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b1f57b4..ec49e7f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -213,6 +213,30 @@ jobs: - clang-12 - libc++-12-dev - libc++abi-12-dev + - toolset: clang + compiler: clang++-13 + cxxstd: "03,11,14,17,20" + os: ubuntu-20.04 + install: + - clang-13 + sources: + - "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-13 main" + source_keys: + - "https://apt.llvm.org/llvm-snapshot.gpg.key" + - toolset: clang + compiler: clang++-13 + cxxstd: "03,11,14,17,20" + os: ubuntu-20.04 + install: + - clang-13 + - libc++-13-dev + - libc++abi-13-dev + sources: + - "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-13 main" + source_keys: + - "https://apt.llvm.org/llvm-snapshot.gpg.key" + cxxflags: -stdlib=libc++ + linkflags: -stdlib=libc++ - name: UBSAN toolset: clang compiler: clang++-12 From 06976ccad7dc565f7032bc6cdbe80a7728482276 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Thu, 23 Dec 2021 15:10:58 +0300 Subject: [PATCH 176/258] Use path-constant to specify path to headers in docs Jamfile. --- doc/Jamfile.v2 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index d73d31d..cce135f 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -5,12 +5,15 @@ # Version 1.0. (See accompanying file LICENSE_1_0.txt # or copy at http://boost.org/LICENSE_1_0.txt) +import project ; import doxygen ; import quickbook ; +path-constant INCLUDES : ../../.. ; + doxygen ref_reference : - [ glob ../../../boost/core/ref.hpp ] + $(INCLUDES)/boost/core/ref.hpp : ENABLE_PREPROCESSING=YES EXPAND_ONLY_PREDEF=YES From 6ae6ff79f10b0ed5abe1ba3c43371583279ef4c3 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Thu, 23 Dec 2021 16:41:32 +0300 Subject: [PATCH 177/258] Deprecated boost/iterator.hpp, emit warnings on inclusion. The header defines boost::iterator template, which is an alias for std::iterator, which is itself deprecated since C++17. Updated test to avoid testing the definition in C++17 onwards to avoid failures due to deprecation warnings from libc++-13. --- doc/changes.qbk | 1 + include/boost/iterator.hpp | 4 +++- test/iterator_test.cpp | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/doc/changes.qbk b/doc/changes.qbk index 88f0d2b..905098b 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -10,6 +10,7 @@ * Added `boost::allocator_traits`, an implementation of `std::allocator_traits`. * Made `boost::pointer_traits` SFINAE friendly. +* `boost/iterator.hpp` is deprecated and will be removed in a future release. The header defines `boost::iterator` template, which is equivalent to `std::iterator` in `` header. However, since `std::iterator` is itself deprecated in C++17, users are advised to remove `boost::iterator` or `std::iterator` use from their code. [endsect] diff --git a/include/boost/iterator.hpp b/include/boost/iterator.hpp index c9c6197..4a780e8 100644 --- a/include/boost/iterator.hpp +++ b/include/boost/iterator.hpp @@ -5,7 +5,9 @@ #ifndef BOOST_ITERATOR_HPP #define BOOST_ITERATOR_HPP -// This header is obsolete and will be deprecated. +#include + +BOOST_HEADER_DEPRECATED("") #include #include // std::ptrdiff_t diff --git a/test/iterator_test.cpp b/test/iterator_test.cpp index c0e64a3..3cbf038 100644 --- a/test/iterator_test.cpp +++ b/test/iterator_test.cpp @@ -8,8 +8,15 @@ // http://www.boost.org/LICENSE_1_0.txt // +#define BOOST_ALLOW_DEPRECATED_HEADERS #define _SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING +#include + +// std::iterator template is deprecated in C++17. Some standard libraries emit warnings +// that cannot be easily suppressed, so disable the tests in C++17 onwards. +#if BOOST_CXX_VERSION < 201703 + #include #include #include @@ -69,3 +76,11 @@ int main() return boost::report_errors(); } + +#else // BOOST_CXX_VERSION < 201703 + +int main() +{ +} + +#endif // BOOST_CXX_VERSION < 201703 From ea7b623b7dc8b9d2e8c9c106f0c0e5d6e0ce0eec Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Fri, 7 Jan 2022 11:16:44 -0500 Subject: [PATCH 178/258] Use consistent section titles in documentation --- doc/alloc_construct.qbk | 2 +- doc/allocator_access.qbk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/alloc_construct.qbk b/doc/alloc_construct.qbk index 2342367..e06e4e8 100644 --- a/doc/alloc_construct.qbk +++ b/doc/alloc_construct.qbk @@ -6,7 +6,7 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) ] -[section:alloc_construct alloc_construct, alloc_destroy] +[section:alloc_construct alloc_construct] [simplesect Authors] diff --git a/doc/allocator_access.qbk b/doc/allocator_access.qbk index 08f71e8..06161ce 100644 --- a/doc/allocator_access.qbk +++ b/doc/allocator_access.qbk @@ -6,7 +6,7 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) ] -[section Allocator Access] +[section allocator_access] [simplesect Authors] From bae7c049b0ae8bc0004d1c32966107432e13fa73 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 19 Jan 2022 17:20:39 +0200 Subject: [PATCH 179/258] Avoid conversion warning in bit_width --- include/boost/core/bit.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/boost/core/bit.hpp b/include/boost/core/bit.hpp index f4305b9..7efb7c7 100644 --- a/include/boost/core/bit.hpp +++ b/include/boost/core/bit.hpp @@ -446,10 +446,13 @@ BOOST_CONSTEXPR bool has_single_bit( T x ) BOOST_NOEXCEPT return x != 0 && ( x & ( x - 1 ) ) == 0; } +// bit_width should return int, https://cplusplus.github.io/LWG/issue3656 + template BOOST_CONSTEXPR T bit_width( T x ) BOOST_NOEXCEPT { - return std::numeric_limits::digits - boost::core::countl_zero( x ); + return static_cast( + std::numeric_limits::digits - boost::core::countl_zero( x ) ); } template From b38c148969a00924406d2fbe8a66dd60f69b6c86 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 8 Feb 2022 21:37:34 +0200 Subject: [PATCH 180/258] Enable -pedantic for the cmath.hpp and bit.hpp tests --- test/Jamfile.v2 | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 567fd37..1e808ab 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -264,19 +264,30 @@ run uncaught_exceptions_np.cpp run no_exceptions_support_test.cpp : ; run no_exceptions_support_test.cpp : : : off : no_exceptions_support_test_nx ; -run cmath_test.cpp ; +run cmath_test.cpp + : : : $(pedantic-errors) ; run cmath_test.cpp : : : BOOST_CORE_USE_GENERIC_CMATH msvc-8.0:no : cmath_test_generic ; -run bit_cast_test.cpp ; -run bit_rotate_test.cpp ; -run bit_countr_test.cpp ; -run bit_countl_test.cpp ; -run bit_width_test.cpp ; -run has_single_bit_test.cpp ; -run bit_floor_test.cpp ; -run bit_ceil_test.cpp ; -run bit_popcount_test.cpp ; -run bit_endian_test.cpp ; +run bit_cast_test.cpp + : : : $(pedantic-errors) ; +run bit_rotate_test.cpp + : : : $(pedantic-errors) ; +run bit_countr_test.cpp + : : : $(pedantic-errors) ; +run bit_countl_test.cpp + : : : $(pedantic-errors) ; +run bit_width_test.cpp + : : : $(pedantic-errors) ; +run has_single_bit_test.cpp + : : : $(pedantic-errors) ; +run bit_floor_test.cpp + : : : $(pedantic-errors) ; +run bit_ceil_test.cpp + : : : $(pedantic-errors) ; +run bit_popcount_test.cpp + : : : $(pedantic-errors) ; +run bit_endian_test.cpp + : : : $(pedantic-errors) ; run type_name_test.cpp ; From cf619432a73372dbddc5dd7434ea0fcedb37700e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 8 Feb 2022 22:00:42 +0200 Subject: [PATCH 181/258] Fix GCC -Wlong-long warnings --- include/boost/core/bit.hpp | 10 +++++----- test/bit_ceil_test.cpp | 4 ++-- test/bit_countl_test.cpp | 4 ++-- test/bit_countr_test.cpp | 4 ++-- test/bit_endian_test.cpp | 2 +- test/bit_floor_test.cpp | 4 ++-- test/bit_popcount_test.cpp | 4 ++-- test/bit_rotate_test.cpp | 4 ++-- test/bit_width_test.cpp | 2 +- test/has_single_bit_test.cpp | 2 +- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/include/boost/core/bit.hpp b/include/boost/core/bit.hpp index 7efb7c7..1288979 100644 --- a/include/boost/core/bit.hpp +++ b/include/boost/core/bit.hpp @@ -82,9 +82,9 @@ BOOST_CONSTEXPR inline int countl_impl( unsigned long x ) BOOST_NOEXCEPT return x? __builtin_clzl( x ): std::numeric_limits::digits; } -BOOST_CONSTEXPR inline int countl_impl( unsigned long long x ) BOOST_NOEXCEPT +BOOST_CONSTEXPR inline int countl_impl( boost::ulong_long_type x ) BOOST_NOEXCEPT { - return x? __builtin_clzll( x ): std::numeric_limits::digits; + return x? __builtin_clzll( x ): std::numeric_limits::digits; } } // namespace detail @@ -224,9 +224,9 @@ BOOST_CONSTEXPR inline int countr_impl( unsigned long x ) BOOST_NOEXCEPT return x? __builtin_ctzl( x ): std::numeric_limits::digits; } -BOOST_CONSTEXPR inline int countr_impl( unsigned long long x ) BOOST_NOEXCEPT +BOOST_CONSTEXPR inline int countr_impl( boost::ulong_long_type x ) BOOST_NOEXCEPT { - return x? __builtin_ctzll( x ): std::numeric_limits::digits; + return x? __builtin_ctzll( x ): std::numeric_limits::digits; } } // namespace detail @@ -365,7 +365,7 @@ BOOST_CORE_POPCOUNT_CONSTEXPR inline int popcount_impl( unsigned long x ) BOOST_ return __builtin_popcountl( x ); } -BOOST_CORE_POPCOUNT_CONSTEXPR inline int popcount_impl( unsigned long long x ) BOOST_NOEXCEPT +BOOST_CORE_POPCOUNT_CONSTEXPR inline int popcount_impl( boost::ulong_long_type x ) BOOST_NOEXCEPT { return __builtin_popcountll( x ); } diff --git a/test/bit_ceil_test.cpp b/test/bit_ceil_test.cpp index 1509d55..53fbb84 100644 --- a/test/bit_ceil_test.cpp +++ b/test/bit_ceil_test.cpp @@ -38,7 +38,7 @@ int main() test_bit_ceil( static_cast( 0 ) ); test_bit_ceil( static_cast( 0 ) ); test_bit_ceil( static_cast( 0 ) ); - test_bit_ceil( static_cast( 0 ) ); + test_bit_ceil( static_cast( 0 ) ); } { @@ -58,7 +58,7 @@ int main() test_bit_ceil( static_cast( x ) ); test_bit_ceil( static_cast( x ) ); test_bit_ceil( static_cast( x ) ); - test_bit_ceil( static_cast( x ) ); + test_bit_ceil( static_cast( x ) ); } return boost::report_errors(); diff --git a/test/bit_countl_test.cpp b/test/bit_countl_test.cpp index e9473c8..c25423e 100644 --- a/test/bit_countl_test.cpp +++ b/test/bit_countl_test.cpp @@ -27,7 +27,7 @@ int main() test_countl( static_cast( 0 ) ); test_countl( static_cast( 0 ) ); test_countl( static_cast( 0 ) ); - test_countl( static_cast( 0 ) ); + test_countl( static_cast( 0 ) ); boost::detail::splitmix64 rng; @@ -39,7 +39,7 @@ int main() test_countl( static_cast( x ) ); test_countl( static_cast( x ) ); test_countl( static_cast( x ) ); - test_countl( static_cast( x ) ); + test_countl( static_cast( x ) ); } return boost::report_errors(); diff --git a/test/bit_countr_test.cpp b/test/bit_countr_test.cpp index dedcf9e..a3b0c96 100644 --- a/test/bit_countr_test.cpp +++ b/test/bit_countr_test.cpp @@ -27,7 +27,7 @@ int main() test_countr( static_cast( 0 ) ); test_countr( static_cast( 0 ) ); test_countr( static_cast( 0 ) ); - test_countr( static_cast( 0 ) ); + test_countr( static_cast( 0 ) ); boost::detail::splitmix64 rng; @@ -39,7 +39,7 @@ int main() test_countr( static_cast( x ) ); test_countr( static_cast( x ) ); test_countr( static_cast( x ) ); - test_countr( static_cast( x ) ); + test_countr( static_cast( x ) ); } return boost::report_errors(); diff --git a/test/bit_endian_test.cpp b/test/bit_endian_test.cpp index b682e1b..06f415e 100644 --- a/test/bit_endian_test.cpp +++ b/test/bit_endian_test.cpp @@ -15,7 +15,7 @@ int main() { - boost::uint64_t v = static_cast( 0x0102030405060708ull ); + boost::uint64_t v = ( static_cast( 0x01020304u ) << 32 ) + 0x05060708u; if( boost::core::endian::native == boost::core::endian::little ) { diff --git a/test/bit_floor_test.cpp b/test/bit_floor_test.cpp index 6afa11e..04dc720 100644 --- a/test/bit_floor_test.cpp +++ b/test/bit_floor_test.cpp @@ -33,7 +33,7 @@ int main() test_bit_floor( static_cast( 0 ) ); test_bit_floor( static_cast( 0 ) ); test_bit_floor( static_cast( 0 ) ); - test_bit_floor( static_cast( 0 ) ); + test_bit_floor( static_cast( 0 ) ); } boost::detail::splitmix64 rng; @@ -46,7 +46,7 @@ int main() test_bit_floor( static_cast( x ) ); test_bit_floor( static_cast( x ) ); test_bit_floor( static_cast( x ) ); - test_bit_floor( static_cast( x ) ); + test_bit_floor( static_cast( x ) ); } return boost::report_errors(); diff --git a/test/bit_popcount_test.cpp b/test/bit_popcount_test.cpp index d5cc678..30d4777 100644 --- a/test/bit_popcount_test.cpp +++ b/test/bit_popcount_test.cpp @@ -26,7 +26,7 @@ int main() test_popcount( static_cast( 0 ) ); test_popcount( static_cast( 0 ) ); test_popcount( static_cast( 0 ) ); - test_popcount( static_cast( 0 ) ); + test_popcount( static_cast( 0 ) ); } boost::detail::splitmix64 rng; @@ -39,7 +39,7 @@ int main() test_popcount( static_cast( x ) ); test_popcount( static_cast( x ) ); test_popcount( static_cast( x ) ); - test_popcount( static_cast( x ) ); + test_popcount( static_cast( x ) ); } return boost::report_errors(); diff --git a/test/bit_rotate_test.cpp b/test/bit_rotate_test.cpp index c99f29c..51bc154 100644 --- a/test/bit_rotate_test.cpp +++ b/test/bit_rotate_test.cpp @@ -152,7 +152,7 @@ int main() } { - unsigned long long x = 0; + boost::ulong_long_type x = 0; BOOST_TEST_EQ( boost::core::rotl( x, i ), x ); BOOST_TEST_EQ( boost::core::rotr( x, i ), x ); } @@ -168,7 +168,7 @@ int main() test_rotate( static_cast( x ) ); test_rotate( static_cast( x ) ); test_rotate( static_cast( x ) ); - test_rotate( static_cast( x ) ); + test_rotate( static_cast( x ) ); } return boost::report_errors(); diff --git a/test/bit_width_test.cpp b/test/bit_width_test.cpp index 1447b90..15ac76d 100644 --- a/test/bit_width_test.cpp +++ b/test/bit_width_test.cpp @@ -87,7 +87,7 @@ int main() test_width( static_cast( x ) ); test_width( static_cast( x ) ); test_width( static_cast( x ) ); - test_width( static_cast( x ) ); + test_width( static_cast( x ) ); } return boost::report_errors(); diff --git a/test/has_single_bit_test.cpp b/test/has_single_bit_test.cpp index 0be8fcd..1e0fe39 100644 --- a/test/has_single_bit_test.cpp +++ b/test/has_single_bit_test.cpp @@ -103,7 +103,7 @@ int main() test_single_bit( static_cast( x ) ); test_single_bit( static_cast( x ) ); test_single_bit( static_cast( x ) ); - test_single_bit( static_cast( x ) ); + test_single_bit( static_cast( x ) ); } return boost::report_errors(); From 6a5f726602c98e63bc447d4c97dfc443f0961f4c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 8 Feb 2022 22:48:01 +0200 Subject: [PATCH 182/258] Add splitmix64_test.cpp --- test/Jamfile.v2 | 3 +++ test/splitmix64_test.cpp | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 test/splitmix64_test.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 1e808ab..fbf6b16 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -328,5 +328,8 @@ run span_deduction_guide_test.cpp ; run as_bytes_test.cpp ; run as_writable_bytes_test.cpp ; +run splitmix64_test.cpp + : : : $(pedantic-errors) ; + use-project /boost/core/swap : ./swap ; build-project ./swap ; diff --git a/test/splitmix64_test.cpp b/test/splitmix64_test.cpp new file mode 100644 index 0000000..7120d7a --- /dev/null +++ b/test/splitmix64_test.cpp @@ -0,0 +1,38 @@ +// Test for boost/core/detail/splitmix64.hpp +// +// Copyright 2022 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include + +int main() +{ + { + boost::detail::splitmix64 rng; + + boost::uint64_t r1 = rng(), x1 = ( boost::uint64_t(0xe220a839u) << 32 ) + 0x7b1dcdafu; + BOOST_TEST_EQ( r1, x1 ); + + for( int i = 0; i < 1000; ++i ) rng(); + + boost::uint64_t r2 = rng(), x2 = ( boost::uint64_t(0xdcad513cu) << 32 ) + 0x211f942du; + BOOST_TEST_EQ( r2, x2 ); + } + + { + boost::detail::splitmix64 rng( 12345 ); + + boost::uint64_t r1 = rng(), x1 = ( boost::uint64_t(0x22118258u) << 32 ) + 0xa9d111a0u; + BOOST_TEST_EQ( r1, x1 ); + + for( int i = 0; i < 1000; ++i ) rng(); + + boost::uint64_t r2 = rng(), x2 = ( boost::uint64_t(0xaaefb4b6u) << 32 ) + 0x5c15e958u; + BOOST_TEST_EQ( r2, x2 ); + } + + return boost::report_errors(); +} From ad63dcda9fff614b37a94953a1503298289947ea Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 8 Feb 2022 22:49:44 +0200 Subject: [PATCH 183/258] Fix -Wlong-long warnings in splitmix64.hpp --- include/boost/core/detail/splitmix64.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/core/detail/splitmix64.hpp b/include/boost/core/detail/splitmix64.hpp index a7dc532..e91ab0a 100644 --- a/include/boost/core/detail/splitmix64.hpp +++ b/include/boost/core/detail/splitmix64.hpp @@ -34,14 +34,14 @@ public: boost::uint64_t operator()() { - x_ += 0x9e3779b97f4a7c15; + x_ += ( boost::uint64_t(0x9e3779b9u) << 32 ) + 0x7f4a7c15u; boost::uint64_t z = x_; z ^= z >> 30; - z *= 0xbf58476d1ce4e5b9; + z *= ( boost::uint64_t(0xbf58476du) << 32 ) + 0x1ce4e5b9u; z ^= z >> 27; - z *= 0x94d049bb133111eb; + z *= ( boost::uint64_t(0x94d049bbu) << 32 ) + 0x133111ebu; z ^= z >> 31; return z; From f12eeb6b9f8f73c23fee1d75e9d18ca90b064dfc Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 8 Feb 2022 22:55:08 +0200 Subject: [PATCH 184/258] Avoid -Wlong-long in bit_rotate_test.cpp --- test/bit_rotate_test.cpp | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/test/bit_rotate_test.cpp b/test/bit_rotate_test.cpp index 51bc154..d37569e 100644 --- a/test/bit_rotate_test.cpp +++ b/test/bit_rotate_test.cpp @@ -103,26 +103,28 @@ int main() BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), 0x44444444 ); } +#define CONST64(x) ((boost::uint64_t(x) << 32) + (x)) + { - boost::uint64_t x = 0x1111111111111111; + boost::uint64_t x = CONST64(0x11111111); - BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), 0x2222222222222222 ); - BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), 0x8888888888888888 ); + BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), CONST64(0x22222222) ); + BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), CONST64(0x88888888) ); - x = 0x2222222222222222; + x = CONST64(0x22222222); - BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), 0x4444444444444444 ); - BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), 0x1111111111111111 ); + BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), CONST64(0x44444444) ); + BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), CONST64(0x11111111) ); - x = 0x4444444444444444; + x = CONST64(0x44444444); - BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), 0x8888888888888888 ); - BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), 0x2222222222222222 ); + BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), CONST64(0x88888888) ); + BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), CONST64(0x22222222) ); - x = 0x8888888888888888; + x = CONST64(0x88888888); - BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), 0x1111111111111111 ); - BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), 0x4444444444444444 ); + BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), CONST64(0x11111111) ); + BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), CONST64(0x44444444) ); } for( int i = -M; i <= M; ++i ) From 89d8efb7ff5ecd55198ce2dd8d3c73644e4f310e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 8 Feb 2022 22:58:45 +0200 Subject: [PATCH 185/258] Avoid -Wlong-long in bit_ceil_test.cpp --- test/bit_ceil_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/bit_ceil_test.cpp b/test/bit_ceil_test.cpp index 53fbb84..2cde75b 100644 --- a/test/bit_ceil_test.cpp +++ b/test/bit_ceil_test.cpp @@ -45,7 +45,7 @@ int main() test_bit_ceil( static_cast( 0x80 ) ); test_bit_ceil( static_cast( 0x8000 ) ); test_bit_ceil( static_cast( 0x80000000 ) ); - test_bit_ceil( static_cast( 0x8000000000000000 ) ); + test_bit_ceil( boost::uint64_t( 1 ) << 63 ); } boost::detail::splitmix64 rng; From b7c987f83c600ce52f031b32b5f20617dcde2fc2 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 15 Feb 2022 02:08:30 +0200 Subject: [PATCH 186/258] Mark quick_exit as inline --- include/boost/core/quick_exit.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/core/quick_exit.hpp b/include/boost/core/quick_exit.hpp index 40ead1d..ff1bda3 100644 --- a/include/boost/core/quick_exit.hpp +++ b/include/boost/core/quick_exit.hpp @@ -33,7 +33,7 @@ extern "C" _Noreturn void quick_exit(int); namespace boost { -BOOST_NORETURN void quick_exit( int code ) BOOST_NOEXCEPT +BOOST_NORETURN inline void quick_exit( int code ) BOOST_NOEXCEPT { #if defined(_MSC_VER) && _MSC_VER < 1900 From 35a4e098540d2c4e024270a75289c4cf3ad94c35 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 15 Feb 2022 04:41:21 +0200 Subject: [PATCH 187/258] Add clang-win to GHA --- .github/workflows/ci.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ec49e7f..0b5e823 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -473,6 +473,10 @@ jobs: cxxstd: "14,17,20,latest" addrmd: 32,64 os: windows-2022 + - toolset: clang-win + cxxstd: "14,17,latest" + addrmd: 32,64 + os: windows-2022 - toolset: gcc cxxstd: "03,11,14,17,2a" addrmd: 64 @@ -519,7 +523,7 @@ jobs: shell: cmd run: | cd ../boost-root - b2 -j %NUMBER_OF_PROCESSORS% libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release + b2 -j %NUMBER_OF_PROCESSORS% libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release embed-manifest-via=linker posix-cmake-subdir: strategy: From 622b7a398aa7765e1e986c4b3285bb1d570ccc6f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 15 Feb 2022 01:34:14 +0200 Subject: [PATCH 188/258] Add core/verbose_terminate_handler.hpp --- .../boost/core/verbose_terminate_handler.hpp | 87 +++++++++++++++++++ test/Jamfile.v2 | 5 ++ test/verbose_terminate_handler_fail.cpp | 48 ++++++++++ 3 files changed, 140 insertions(+) create mode 100644 include/boost/core/verbose_terminate_handler.hpp create mode 100644 test/verbose_terminate_handler_fail.cpp diff --git a/include/boost/core/verbose_terminate_handler.hpp b/include/boost/core/verbose_terminate_handler.hpp new file mode 100644 index 0000000..b831b49 --- /dev/null +++ b/include/boost/core/verbose_terminate_handler.hpp @@ -0,0 +1,87 @@ +#ifndef BOOST_CORE_VERBOSE_TERMINATE_HANDLER_HPP_INCLUDED +#define BOOST_CORE_VERBOSE_TERMINATE_HANDLER_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// Copyright 2022 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ +namespace core +{ + +BOOST_NORETURN void verbose_terminate_handler() +{ + std::set_terminate( 0 ); + +#if defined(BOOST_NO_EXCEPTIONS) + + std::fputs( "std::terminate called with exceptions disabled", stderr ); + +#else + + try + { + throw; + } + catch( std::exception const& x ) + { +#if defined(BOOST_NO_RTTI) + + char const * typeid_name = "unknown (RTTI is disabled)"; + +#else + + char const * typeid_name = typeid( x ).name(); + + boost::core::scoped_demangled_name typeid_demangled_name( typeid_name ); + + if( typeid_demangled_name.get() != 0 ) + { + typeid_name = typeid_demangled_name.get(); + } + +#endif + + boost::source_location loc = boost::get_throw_location( x ); + + std::fprintf( stderr, + "std::terminate called after throwing an exception:\n" + " type: %s\n" + " what(): %s\n" + " location: %s:%lu:%lu in function '%s'\n", + + typeid_name, + x.what(), + loc.file_name(), static_cast( loc.line() ), + static_cast( loc.column() ), loc.function_name() + ); + } + catch( ... ) + { + std::fputs( "std::terminate called after throwing an unknown exception", stderr ); + } + +#endif + + std::abort(); +} + +} // namespace core +} // namespace boost + +#endif // #ifndef BOOST_CORE_VERBOSE_TERMINATE_HANDLER_HPP_INCLUDED diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index fbf6b16..28a5be2 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -331,5 +331,10 @@ run as_writable_bytes_test.cpp ; run splitmix64_test.cpp : : : $(pedantic-errors) ; +run-fail verbose_terminate_handler_fail.cpp ; +run-fail verbose_terminate_handler_fail.cpp : : : off : verbose_terminate_handler_fail_nx ; +run-fail verbose_terminate_handler_fail.cpp : : : off : verbose_terminate_handler_fail_nr ; +run-fail verbose_terminate_handler_fail.cpp : : : off off : verbose_terminate_handler_fail_nxr ; + use-project /boost/core/swap : ./swap ; build-project ./swap ; diff --git a/test/verbose_terminate_handler_fail.cpp b/test/verbose_terminate_handler_fail.cpp new file mode 100644 index 0000000..07f8ef5 --- /dev/null +++ b/test/verbose_terminate_handler_fail.cpp @@ -0,0 +1,48 @@ +// Copyright 2022 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#if defined(_MSC_VER) +# pragma warning(disable: 4702) // unreachable code +#endif + +#include +#include +#include +#include +#if defined(_MSC_VER) && defined(_CPPLIB_VER) && defined(_DEBUG) +# include +#endif + +int main() +{ +#if defined(_MSC_VER) && (_MSC_VER > 1310) + // disable message boxes on assert(), abort() + ::_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); +#endif +#if defined(_MSC_VER) && defined(_CPPLIB_VER) && defined(_DEBUG) + // disable message boxes on iterator debugging violations + _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR ); +#endif + + std::set_terminate( boost::core::verbose_terminate_handler ); + + boost::throw_with_location( std::exception() ); +} + +#if defined(BOOST_NO_EXCEPTIONS) + +void boost::throw_exception( std::exception const& x ) +{ + std::fprintf( stderr, "throw_exception: %s\n\n", x.what() ); + std::terminate(); +} + +void boost::throw_exception( std::exception const& x, boost::source_location const& ) +{ + std::fprintf( stderr, "throw_exception: %s\n\n", x.what() ); + std::terminate(); +} + +#endif From ed84fc4e2376dae2bfcb4831b7e696132ac9b71b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 15 Feb 2022 01:51:15 +0200 Subject: [PATCH 189/258] Document verbose_terminate_handler --- doc/core.qbk | 3 +- doc/verbose_terminate_handler.qbk | 70 +++++++++++++++++++ .../boost/core/verbose_terminate_handler.hpp | 2 +- 3 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 doc/verbose_terminate_handler.qbk diff --git a/doc/core.qbk b/doc/core.qbk index fbbecf6..33e2faf 100644 --- a/doc/core.qbk +++ b/doc/core.qbk @@ -34,7 +34,7 @@ criteria for inclusion is that the utility component be: * simple, * used by other Boost libraries, and * not dependent on any other Boost modules except Core - itself, Config, Assert, or Static Assert. + itself, Config, Assert, StaticAssert, or ThrowException. [endsect] @@ -72,3 +72,4 @@ criteria for inclusion is that the utility component be: [include type_name.qbk] [include uncaught_exceptions.qbk] [include use_default.qbk] +[include verbose_terminate_handler.qbk] diff --git a/doc/verbose_terminate_handler.qbk b/doc/verbose_terminate_handler.qbk new file mode 100644 index 0000000..35f8bff --- /dev/null +++ b/doc/verbose_terminate_handler.qbk @@ -0,0 +1,70 @@ +[/ + Copyright 2022 Peter Dimov + Distributed under the Boost Software License, Version 1.0. + https://boost.org/LICENSE_1_0.txt +] + +[section:verbose_terminate_handler verbose_terminate_handler] + +[simplesect Authors] + +* Peter Dimov + +[endsimplesect] + +[section Header ] + +The header `` defines +the function `void boost::core::verbose_terminate_handler()`. Its +purpose is to be set as a terminate handler as in +``` + std::set_terminate( boost::core::verbose_terminate_handler ); +``` + +When invoked, the function prints information about the current +uncaught exception to `stderr` and then calls `std::abort`. + +[section Synopsis] + +`` +namespace boost +{ +namespace core +{ + +[[noreturn]] void verbose_terminate_handler(); + +} // namespace core +} // namespace boost +`` + +[endsect] + +[section Example] + +``` +#include +#include +#include + +int main() +{ + std::set_terminate( boost::core::verbose_terminate_handler ); + boost::throw_with_location( std::exception() ); +} +``` + +Sample output: +``` +std::terminate called after throwing an exception: + + type: class boost::detail::with_throw_location + what(): Unknown exception + location: example.cpp:8:12 in function 'main' +``` + +[endsect] + +[endsect] + +[endsect] diff --git a/include/boost/core/verbose_terminate_handler.hpp b/include/boost/core/verbose_terminate_handler.hpp index b831b49..408b12e 100644 --- a/include/boost/core/verbose_terminate_handler.hpp +++ b/include/boost/core/verbose_terminate_handler.hpp @@ -60,7 +60,7 @@ BOOST_NORETURN void verbose_terminate_handler() boost::source_location loc = boost::get_throw_location( x ); std::fprintf( stderr, - "std::terminate called after throwing an exception:\n" + "std::terminate called after throwing an exception:\n\n" " type: %s\n" " what(): %s\n" " location: %s:%lu:%lu in function '%s'\n", From 188ca25bf389c5f7936ce19cf2f810642bbb1d86 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 15 Feb 2022 02:03:40 +0200 Subject: [PATCH 190/258] Mark verbose_terminate_handler as inline --- include/boost/core/verbose_terminate_handler.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/core/verbose_terminate_handler.hpp b/include/boost/core/verbose_terminate_handler.hpp index 408b12e..2b82b6b 100644 --- a/include/boost/core/verbose_terminate_handler.hpp +++ b/include/boost/core/verbose_terminate_handler.hpp @@ -24,7 +24,7 @@ namespace boost namespace core { -BOOST_NORETURN void verbose_terminate_handler() +BOOST_NORETURN inline void verbose_terminate_handler() { std::set_terminate( 0 ); From ec91f29d56297c6a45166f77bf659b5783dab425 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 15 Feb 2022 05:10:26 +0200 Subject: [PATCH 191/258] Disable msvc warnings --- test/verbose_terminate_handler_fail.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/verbose_terminate_handler_fail.cpp b/test/verbose_terminate_handler_fail.cpp index 07f8ef5..31c6bc4 100644 --- a/test/verbose_terminate_handler_fail.cpp +++ b/test/verbose_terminate_handler_fail.cpp @@ -4,6 +4,8 @@ #if defined(_MSC_VER) # pragma warning(disable: 4702) // unreachable code +# pragma warning(disable: 4530) // C++ exception handler used +# pragma warning(disable: 4577) // 'noexcept' used #endif #include From 230dd8300221b690cdd71b1a4c81290d07dac5a5 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 15 Feb 2022 05:10:41 +0200 Subject: [PATCH 192/258] Add newlines, fflush --- include/boost/core/verbose_terminate_handler.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/boost/core/verbose_terminate_handler.hpp b/include/boost/core/verbose_terminate_handler.hpp index 2b82b6b..b607470 100644 --- a/include/boost/core/verbose_terminate_handler.hpp +++ b/include/boost/core/verbose_terminate_handler.hpp @@ -30,7 +30,7 @@ BOOST_NORETURN inline void verbose_terminate_handler() #if defined(BOOST_NO_EXCEPTIONS) - std::fputs( "std::terminate called with exceptions disabled", stderr ); + std::fputs( "std::terminate called with exceptions disabled\n", stderr ); #else @@ -73,11 +73,12 @@ BOOST_NORETURN inline void verbose_terminate_handler() } catch( ... ) { - std::fputs( "std::terminate called after throwing an unknown exception", stderr ); + std::fputs( "std::terminate called after throwing an unknown exception\n", stderr ); } #endif + std::fflush( stdout ); std::abort(); } From a32c1ee7acf4f2ce429ddb0b6c8f63a29da4202c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 15 Feb 2022 05:11:37 +0200 Subject: [PATCH 193/258] Disable test under CMake, CTest doesn't like crashing tests --- test/Jamfile.v2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 28a5be2..ab00563 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -331,7 +331,7 @@ run as_writable_bytes_test.cpp ; run splitmix64_test.cpp : : : $(pedantic-errors) ; -run-fail verbose_terminate_handler_fail.cpp ; +run-fail verbose_terminate_handler_fail.cpp : ; run-fail verbose_terminate_handler_fail.cpp : : : off : verbose_terminate_handler_fail_nx ; run-fail verbose_terminate_handler_fail.cpp : : : off : verbose_terminate_handler_fail_nr ; run-fail verbose_terminate_handler_fail.cpp : : : off off : verbose_terminate_handler_fail_nxr ; From dbefea96316465c501bcb853642cc855b03a462b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 15 Feb 2022 20:54:37 +0200 Subject: [PATCH 194/258] Update revision history --- doc/changes.qbk | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/changes.qbk b/doc/changes.qbk index 905098b..a11f7e1 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -11,6 +11,9 @@ * Added `boost::allocator_traits`, an implementation of `std::allocator_traits`. * Made `boost::pointer_traits` SFINAE friendly. * `boost/iterator.hpp` is deprecated and will be removed in a future release. The header defines `boost::iterator` template, which is equivalent to `std::iterator` in `` header. However, since `std::iterator` is itself deprecated in C++17, users are advised to remove `boost::iterator` or `std::iterator` use from their code. +* Added `boost::core::verbose_terminate_handler`, a utility function intended + to be passed to `std::set_terminate` that prints information about the + uncaught exception to `stderr`. [endsect] From f326683d42614d03c4849fe9b40c7264b260900a Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Sat, 12 Mar 2022 00:51:52 -0500 Subject: [PATCH 195/258] Add allocator_construct and allocator_destroy tests to Jamfile --- test/Jamfile.v2 | 2 ++ test/allocator_construct_test.cpp | 2 +- test/allocator_destroy_test.cpp | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index ab00563..4bb7499 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -240,6 +240,8 @@ run allocator_allocate_hint_test.cpp ; run allocator_deallocate_test.cpp ; run allocator_max_size_test.cpp ; run allocator_soccc_test.cpp ; +run allocator_construct_test.cpp ; +run allocator_destroy_test.cpp ; run allocator_traits_test.cpp ; lib lib_typeid : lib_typeid.cpp : shared:LIB_TYPEID_DYN_LINK=1 ; diff --git a/test/allocator_construct_test.cpp b/test/allocator_construct_test.cpp index ded2278..2bd1db2 100644 --- a/test/allocator_construct_test.cpp +++ b/test/allocator_construct_test.cpp @@ -36,7 +36,7 @@ int main() } #if !defined(BOOST_NO_CXX11_ALLOCATOR) { - A1 a; + A2 a; int i = 0; boost::allocator_construct(a, &i, 5); BOOST_TEST_EQ(i, 6); diff --git a/test/allocator_destroy_test.cpp b/test/allocator_destroy_test.cpp index 9f2e0c0..0b5b64e 100644 --- a/test/allocator_destroy_test.cpp +++ b/test/allocator_destroy_test.cpp @@ -52,7 +52,7 @@ int main() } #if !defined(BOOST_NO_CXX11_ALLOCATOR) { - A1 a; + A2 a; int i = 5; boost::allocator_destroy(a, &i); BOOST_TEST_EQ(i, 0); From c4deb479fdd4e69dd1e20e1a917cb07231d0d07b Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Sat, 12 Mar 2022 01:06:00 -0500 Subject: [PATCH 196/258] Add detection support for single argument construct and destroy --- include/boost/core/allocator_access.hpp | 135 ++++++++++++++++-------- test/allocator_construct_test.cpp | 16 +++ test/allocator_destroy_test.cpp | 4 - 3 files changed, 106 insertions(+), 49 deletions(-) diff --git a/include/boost/core/allocator_access.hpp b/include/boost/core/allocator_access.hpp index 247ad75..e8e5f58 100644 --- a/include/boost/core/allocator_access.hpp +++ b/include/boost/core/allocator_access.hpp @@ -1,5 +1,5 @@ /* -Copyright 2020-2021 Glen Joseph Fernandes +Copyright 2020-2022 Glen Joseph Fernandes (glenjofe@gmail.com) Distributed under the Boost Software License, Version 1.0. @@ -427,9 +427,72 @@ allocator_allocate(A& a, typename allocator_size_type::type n, } #endif +namespace detail { + +#if defined(BOOST_NO_CXX11_ALLOCATOR) +template +struct alloc_no { + char x, y; +}; + +template +class alloc_has_construct { + template + static alloc_no + check(int); + + template + static alloc_no + check(int); + + template + static alloc_no + check(int); + + template + static char check(long); + +public: + static const bool value = sizeof(check(0)) > 1; +}; +#else +template +class alloc_has_construct { + template + static auto check(int) + -> alloc_no().construct(std::declval(), + std::declval()...))>; + + template + static char check(long); + +public: + BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) > 1; +}; +#endif + +template +struct alloc_if { }; + +template +struct alloc_if { + typedef T type; +}; + +} /* detail */ + #if defined(BOOST_NO_CXX11_ALLOCATOR) template -inline void +inline typename detail::alloc_if::value>::type +allocator_construct(A& a, T* p) +{ + a.construct(p); +} + +template +inline typename detail::alloc_if::value>::type allocator_construct(A&, T* p) { ::new((void*)p) T(); @@ -467,24 +530,6 @@ allocator_construct(A&, T* p, V& v) } #endif #else -namespace detail { - -template -class alloc_has_construct { - template - static auto check(int) - -> alloc_no().construct(std::declval(), - std::declval()...))>; - - template - static char check(long); - -public: - BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) > 1; -}; - -} /* detail */ - template inline typename std::enable_if::value>::type @@ -502,17 +547,30 @@ allocator_construct(A&, T* p, Args&&... args) } #endif -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -inline void -allocator_destroy(A&, T* p) -{ - p->~T(); - (void)p; -} -#else namespace detail { +#if defined(BOOST_NO_CXX11_ALLOCATOR) +template +class alloc_has_destroy { + template + static alloc_no + check(int); + + template + static alloc_no + check(int); + + template + static alloc_no + check(int); + + template + static char check(long); + +public: + static const bool value = sizeof(check(0)) > 1; +}; +#else template class alloc_has_destroy { template @@ -525,33 +583,28 @@ class alloc_has_destroy { public: BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) > 1; }; +#endif } /* detail */ template -inline typename std::enable_if::value>::type +inline typename detail::alloc_if::value>::type allocator_destroy(A& a, T* p) { a.destroy(p); } template -inline typename std::enable_if::value>::type +inline typename detail::alloc_if::value>::type allocator_destroy(A&, T* p) { p->~T(); (void)p; } -#endif namespace detail { #if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct alloc_no { - char x, y; -}; - template class alloc_has_max_size { template @@ -587,14 +640,6 @@ public: }; #endif -template -struct alloc_if { }; - -template -struct alloc_if { - typedef T type; -}; - } /* detail */ template diff --git a/test/allocator_construct_test.cpp b/test/allocator_construct_test.cpp index 2bd1db2..30f2d0e 100644 --- a/test/allocator_construct_test.cpp +++ b/test/allocator_construct_test.cpp @@ -26,6 +26,16 @@ struct A2 { }; #endif +template +struct A3 { + typedef T value_type; + A3() { } + template + void construct(U* p) { + ::new((void*)p) U(1); + } +}; + int main() { { @@ -42,5 +52,11 @@ int main() BOOST_TEST_EQ(i, 6); } #endif + { + A3 a; + int i = 0; + boost::allocator_construct(a, &i); + BOOST_TEST_EQ(i, 1); + } return boost::report_errors(); } diff --git a/test/allocator_destroy_test.cpp b/test/allocator_destroy_test.cpp index 0b5b64e..04d794e 100644 --- a/test/allocator_destroy_test.cpp +++ b/test/allocator_destroy_test.cpp @@ -29,7 +29,6 @@ struct A1 { A1() { } }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct A2 { typedef T value_type; @@ -39,7 +38,6 @@ struct A2 { *p = U(); } }; -#endif int main() { @@ -50,13 +48,11 @@ int main() BOOST_TEST_EQ(S::count, 0); ::new((void*)&s) S(); } -#if !defined(BOOST_NO_CXX11_ALLOCATOR) { A2 a; int i = 5; boost::allocator_destroy(a, &i); BOOST_TEST_EQ(i, 0); } -#endif return boost::report_errors(); } From 4defdfd23352672dc386b91e966de4cc13e71ca8 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Sat, 12 Mar 2022 10:14:59 -0500 Subject: [PATCH 197/258] Add allocator_construct_n to allocator_access and deprecate alloc_construct --- doc/alloc_construct.qbk | 149 ------------------------ doc/allocator_access.qbk | 60 +++++++++- doc/core.qbk | 1 - include/boost/core/alloc_construct.hpp | 88 ++------------ include/boost/core/allocator_access.hpp | 69 +++++++++++ test/Jamfile.v2 | 2 + test/allocator_construct_n_test.cpp | 47 ++++++++ test/allocator_destroy_n_test.cpp | 30 +++++ 8 files changed, 214 insertions(+), 232 deletions(-) delete mode 100644 doc/alloc_construct.qbk create mode 100644 test/allocator_construct_n_test.cpp create mode 100644 test/allocator_destroy_n_test.cpp diff --git a/doc/alloc_construct.qbk b/doc/alloc_construct.qbk deleted file mode 100644 index e06e4e8..0000000 --- a/doc/alloc_construct.qbk +++ /dev/null @@ -1,149 +0,0 @@ -[/ -Copyright 2019 Glen Joseph Fernandes -(glenjofe@gmail.com) - -Distributed under the Boost Software License, Version 1.0. -(http://www.boost.org/LICENSE_1_0.txt) -] - -[section:alloc_construct alloc_construct] - -[simplesect Authors] - -* Glen Fernandes - -[endsimplesect] - -[section Overview] - -The header provides function templates -`alloc_construct`, `alloc_construct_n`, `alloc_destroy`, and `alloc_destroy_n` -for allocator aware and exception safe construction and destruction of objects -and arrays. - -[endsect] - -[section Example] - -The following example allocates storage for an array of `n` elements of `T` -using an allocator `a` and constructs `T` elements in that storage. If any -exception was thrown during construction of an element, the constructed -elements are destroyed in reverse order. - -``` -template -auto create(A& a, std::size_t n) -{ - auto p = a.allocate(n); - try { - boost::alloc_construct_n(a, boost::to_address(p), n); - } catch (...) { - a.deallocate(p, n); - throw; - } - return p; -} -``` - -[endsect] - -[section Reference] - -``` -namespace boost { - -template -void alloc_destroy(A& a, T* p); - -template -void alloc_destroy_n(A& a, T* p, std::size_t n); - -template -void alloc_construct(A& a, T* p, Args&&... args); - -template -void alloc_construct_n(A& a, T* p, std::size_t n); - -template -void alloc_construct_n(A& a, T* p, std::size_t n, const T* l, std::size_t m); - -template -void alloc_construct_n(A& a, T* p, std::size_t n, I begin); - -} /* boost */ -``` - -[section Functions] - -[variablelist -[[`template void alloc_destroy(A& a, T* p);`] -[[variablelist -[[Requires][`A` is an /Allocator/]] -[[Effects][`std::allocator_traits::destroy(a, p)`.]]]]] -[[`template void alloc_destroy_n(A& a, T* p, -std::size_t n);`] -[[variablelist -[[Requires][`A` is an /Allocator/]] -[[Effects] -[Destroys each `i`-th element in reverse order by calling -`std::allocator_traits::destroy(a, &p[i])`.]]]]] -[[`template void alloc_construct(A& a, T* p, -Args&&... args);`] -[[variablelist -[[Requires][`A` is an /Allocator/]] -[[Effects] -[`std::allocator_traits::construct(a, p, std::forward(args)...)`.]]]]] -[[`template void alloc_construct_n(A& a, T* p, -std::size_t n);`] -[[variablelist -[[Requires][`A` is an /Allocator/]] -[[Effects] -[Constructs each `i`-th element in order by calling -`std::allocator_traits::construct(a, &p[i])`.]] -[[Remarks] -[If an exception is thrown destroys each already constructed `j`-th element in -reverse order by calling `std::allocator_traits::destroy(a, &p[j])`.]]]]] -[[`template void alloc_construct_n(A& a, T* p, std::size_t n, -const T* l, std::size_t m);`] -[[variablelist -[[Requires][`A` is an /Allocator/]] -[[Effects] -[Constructs each `i`-th element in order by calling -`std::allocator_traits::construct(a, &p[i], l[i % m])`.]] -[[Remarks] -[If an exception is thrown destroys each already constructed `j`-th element in -reverse order by calling `std::allocator_traits::destroy(a, &p[j])`.]]]]] -[[`template void alloc_construct_n(A& a, T* p, -std::size_t n, I begin);`] -[[variablelist -[[Requires] -[[itemized_list -[`A` is an /Allocator/][`I` is an /InputIterator/]]]] -[[Effects] -[Constructs each `i`-th element in order by calling -`std::allocator_traits::construct(a, &p[i], *begin++])`.]] -[[Remarks] -[If an exception is thrown destroys each already constructed `j`-th element in -reverse order by calling `std::allocator_traits::destroy(a, &p[j])`.]]]]]] - -[endsect] - -[endsect] - -[section Compatibility] - -When `BOOST_NO_CXX11_ALLOCATOR` is defined, and the C++11 allocator model is -not supported, these functions invoke constructors and destructors directly -without going through the supplied allocator. - -[endsect] - -[section Acknowledgments] - -Glen Fernandes originally implemented this functionality in Boost.Smart_Ptr and -later moved these functions to Boost.Core for use in other Boost libraries, -such as Boost.Multi_Array and Boost.Histogram. - -[endsect] - -[endsect] diff --git a/doc/allocator_access.qbk b/doc/allocator_access.qbk index 06161ce..1a0c82f 100644 --- a/doc/allocator_access.qbk +++ b/doc/allocator_access.qbk @@ -1,5 +1,5 @@ [/ -Copyright 2020 Glen Joseph Fernandes +Copyright 2020-2022 Glen Joseph Fernandes (glenjofe@gmail.com) Distributed under the Boost Software License, Version 1.0. @@ -21,6 +21,9 @@ templates to simplify allocator use. It provides the same functionality as the C++ standard library `std::allocator_traits` but with individual templates for each allocator feature. +It also adds additional functionality for allocator aware exception safe +construction and destruction of arrays. + These facilities also simplify existing libraries by avoiding having to check for `BOOST_NO_CXX11_ALLOCATOR` and conditionally use `std::allocator_traits`. @@ -51,6 +54,26 @@ public: In C++11 or above, aliases such as `boost::allocator_pointer_t` can be used instead of `typename boost::allocator_pointer::type`. +The following example allocates storage for an array of `n` elements of `T` +using an allocator `a` and constructs `T` elements in that storage. If any +exception was thrown during construction of an element, the constructed +elements are destroyed in reverse order. + +``` +template +auto create(A& a, std::size_t n) +{ + auto p = a.allocate(n); + try { + boost::allocator_construct_n(a, boost::to_address(p), n); + } catch (...) { + a.deallocate(p, n); + throw; + } + return p; +} +``` + [endsect] [section Reference] @@ -150,9 +173,22 @@ void allocator_deallocate(A& a, allocator_pointer_t p, template void allocator_construct(A& a, T* p, Args&&... args); +template +void allocator_construct_n(A& a, T* p, std::size_t n); + +template +void allocator_construct_n(A& a, T* p, std::size_t n, const T* l, + std::size_t m); + +template +void allocator_construct_n(A& a, T* p, std::size_t n, I begin); + template void allocator_destroy(A& a, T* p); +template +void allocator_destroy_n(A& a, T* p, std::size_t n); + template allocator_size_type_t allocator_max_size(const A& a); @@ -220,8 +256,30 @@ allocator_size_type_t n);`] void allocator_construct(A& a, T*p, Args&&... args);`] [Calls `a.construct(p, std::forward(args)...)` if valid, otherwise calls `::new(static_cast(p)) T(std::forward(args)...)`.]] +[[`template +void alloc_construct_n(A& a, T* p, std::size_t n);`] +[Constructs each `i`-th element in order by calling +`boost::allocator_construct(a, &p[i])`. +If an exception is thrown destroys each already constructed `j`-th element in +reverse order by calling `boost::allocator_destroy(a, &p[j])`.]] +[[`template +void alloc_construct_n(A& a, T* p, std::size_t n, const T* l, std::size_t m);`] +[Constructs each `i`-th element in order by calling +`boost::allocator_construct(a, &p[i], l[i % m])`. +If an exception is thrown destroys each already constructed `j`-th element in +reverse order by calling `boost::allocator_destroy(a, &p[j])`.]] +[[`template +void alloc_construct_n(A& a, T* p, std::size_t n, I begin);`] +[Constructs each `i`-th element in order by calling +`boost::allocator_construct(a, &p[i], *begin++)`. +If an exception is thrown destroys each already constructed `j`-th element in +reverse order by calling `boost::allocator_destroy(a, &p[j])`.]] [[`template void allocator_destroy(A& a, T* p);`] [Calls `a.destroy(p)` if valid, otherwise calls `p->~T()`.]] +[[`template +void allocator_destroy_n(A& a, T* p, std::size_t n);`] +[Destroys each `i`-th element in reverse order by calling +`boost::allocator_destroy(a, &p[i])`.]] [[`template allocator_size_type_t allocator_max_size(const A& a);`] [Returns `a.max_size()` if valid, otherwise returns `std::numeric_limits >::max() / diff --git a/doc/core.qbk b/doc/core.qbk index 33e2faf..fd677c4 100644 --- a/doc/core.qbk +++ b/doc/core.qbk @@ -43,7 +43,6 @@ criteria for inclusion is that the utility component be: [include addressof.qbk] [include allocator_access.qbk] [include allocator_traits.qbk] -[include alloc_construct.qbk] [include bit.qbk] [include checked_delete.qbk] [include cmath.qbk] diff --git a/include/boost/core/alloc_construct.hpp b/include/boost/core/alloc_construct.hpp index e390730..075d3cb 100644 --- a/include/boost/core/alloc_construct.hpp +++ b/include/boost/core/alloc_construct.hpp @@ -8,6 +8,9 @@ Distributed under the Boost Software License, Version 1.0. #ifndef BOOST_CORE_ALLOC_CONSTRUCT_HPP #define BOOST_CORE_ALLOC_CONSTRUCT_HPP +/* +This functionality is now in . +*/ #include namespace boost { @@ -23,56 +26,9 @@ template inline void alloc_destroy_n(A& a, T* p, std::size_t n) { - while (n > 0) { - boost::allocator_destroy(a, p + --n); - } + boost::allocator_destroy_n(a, p, n); } -template -inline void -alloc_destroy(noinit_adaptor&, T* p) -{ - p->~T(); -} - -template -inline void -alloc_destroy_n(noinit_adaptor&, T* p, std::size_t n) -{ - while (n > 0) { - p[--n].~T(); - } -} - -namespace detail { - -template -class alloc_destroyer { -public: - alloc_destroyer(A& a, T* p) BOOST_NOEXCEPT - : a_(a), - p_(p), - n_(0) { } - - ~alloc_destroyer() { - boost::alloc_destroy_n(a_, p_, n_); - } - - std::size_t& size() BOOST_NOEXCEPT { - return n_; - } - -private: - alloc_destroyer(const alloc_destroyer&); - alloc_destroyer& operator=(const alloc_destroyer&); - - A& a_; - T* p_; - std::size_t n_; -}; - -} /* detail */ - template inline void alloc_construct(A& a, T* p) @@ -117,51 +73,21 @@ template inline void alloc_construct_n(A& a, T* p, std::size_t n) { - detail::alloc_destroyer hold(a, p); - for (std::size_t& i = hold.size(); i < n; ++i) { - boost::allocator_construct(a, p + i); - } - hold.size() = 0; + boost::allocator_construct_n(a, p, n); } template inline void alloc_construct_n(A& a, T* p, std::size_t n, const T* l, std::size_t m) { - detail::alloc_destroyer hold(a, p); - for (std::size_t& i = hold.size(); i < n; ++i) { - boost::allocator_construct(a, p + i, l[i % m]); - } - hold.size() = 0; + boost::allocator_construct_n(a, p, n, l, m); } template inline void alloc_construct_n(A& a, T* p, std::size_t n, I b) { - detail::alloc_destroyer hold(a, p); - for (std::size_t& i = hold.size(); i < n; void(++i), void(++b)) { - boost::allocator_construct(a, p + i, *b); - } - hold.size() = 0; -} - -template -inline void -alloc_construct(noinit_adaptor&, T* p) -{ - ::new(static_cast(p)) T; -} - -template -inline void -alloc_construct_n(noinit_adaptor& a, T* p, std::size_t n) -{ - detail::alloc_destroyer, T> hold(a, p); - for (std::size_t& i = hold.size(); i < n; ++i) { - ::new(static_cast(p + i)) T; - } - hold.size() = 0; + boost::allocator_construct_n(a, p, n, b); } } /* boost */ diff --git a/include/boost/core/allocator_access.hpp b/include/boost/core/allocator_access.hpp index e8e5f58..7717ba0 100644 --- a/include/boost/core/allocator_access.hpp +++ b/include/boost/core/allocator_access.hpp @@ -714,6 +714,75 @@ allocator_select_on_container_copy_construction(const A& a) return a; } +template +inline void +allocator_destroy_n(A& a, T* p, std::size_t n) +{ + while (n > 0) { + boost::allocator_destroy(a, p + --n); + } +} + +namespace detail { + +template +class alloc_destroyer { +public: + alloc_destroyer(A& a, T* p) BOOST_NOEXCEPT + : a_(a), p_(p), n_(0) { } + + ~alloc_destroyer() { + boost::allocator_destroy_n(a_, p_, n_); + } + + std::size_t& size() BOOST_NOEXCEPT { + return n_; + } + +private: + alloc_destroyer(const alloc_destroyer&); + alloc_destroyer& operator=(const alloc_destroyer&); + + A& a_; + T* p_; + std::size_t n_; +}; + +} /* detail */ + +template +inline void +allocator_construct_n(A& a, T* p, std::size_t n) +{ + detail::alloc_destroyer d(a, p); + for (std::size_t& i = d.size(); i < n; ++i) { + boost::allocator_construct(a, p + i); + } + d.size() = 0; +} + +template +inline void +allocator_construct_n(A& a, T* p, std::size_t n, const T* l, std::size_t m) +{ + detail::alloc_destroyer d(a, p); + for (std::size_t& i = d.size(); i < n; ++i) { + boost::allocator_construct(a, p + i, l[i % m]); + } + d.size() = 0; +} + +template +inline void +allocator_construct_n(A& a, T* p, std::size_t n, I b) +{ + detail::alloc_destroyer d(a, p); + for (std::size_t& i = d.size(); i < n; void(++i), void(++b)) { + boost::allocator_construct(a, p + i, *b); + } + d.size() = 0; +} + #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) template using allocator_value_type_t = typename allocator_value_type::type; diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 4bb7499..71a6544 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -242,6 +242,8 @@ run allocator_max_size_test.cpp ; run allocator_soccc_test.cpp ; run allocator_construct_test.cpp ; run allocator_destroy_test.cpp ; +run allocator_construct_n_test.cpp ; +run allocator_destroy_n_test.cpp ; run allocator_traits_test.cpp ; lib lib_typeid : lib_typeid.cpp : shared:LIB_TYPEID_DYN_LINK=1 ; diff --git a/test/allocator_construct_n_test.cpp b/test/allocator_construct_n_test.cpp new file mode 100644 index 0000000..2e0b898 --- /dev/null +++ b/test/allocator_construct_n_test.cpp @@ -0,0 +1,47 @@ +/* +Copyright 2022 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include + +template +struct A { + typedef T value_type; + A() { } +}; + +int main() +{ + { + A a; + int i[3] = { 5, 5, 5 }; + boost::allocator_construct_n(a, &i[0], 3); + BOOST_TEST_EQ(i[0], 0); + BOOST_TEST_EQ(i[1], 0); + BOOST_TEST_EQ(i[2], 0); + } + { + A a; + int i[4] = { 5, 5, 5, 5 }; + int j[2] = { 1, 2 }; + boost::allocator_construct_n(a, &i[0], 4, &j[0], 2); + BOOST_TEST_EQ(i[0], 1); + BOOST_TEST_EQ(i[1], 2); + BOOST_TEST_EQ(i[2], 1); + BOOST_TEST_EQ(i[3], 2); + } + { + A a; + int i[3] = { 5, 5, 5 }; + int j[3] = { 1, 2, 3 }; + boost::allocator_construct_n(a, &i[0], 3, &j[0]); + BOOST_TEST_EQ(i[0], 1); + BOOST_TEST_EQ(i[1], 2); + BOOST_TEST_EQ(i[2], 3); + } + return boost::report_errors(); +} diff --git a/test/allocator_destroy_n_test.cpp b/test/allocator_destroy_n_test.cpp new file mode 100644 index 0000000..fc19469 --- /dev/null +++ b/test/allocator_destroy_n_test.cpp @@ -0,0 +1,30 @@ +/* +Copyright 2022 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include + +template +struct A { + typedef T value_type; + A() { } + template + void destroy(U* p) { + *p = U(); + } +}; + +int main() +{ + A a; + int i[3] = { 5, 5, 5 }; + boost::allocator_destroy_n(a, &i[0], 3); + BOOST_TEST_EQ(i[0], 0); + BOOST_TEST_EQ(i[1], 0); + BOOST_TEST_EQ(i[2], 0); + return boost::report_errors(); +} From 5e0ff1680f696868add3ca8d614c095475fce454 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Tue, 15 Mar 2022 11:58:38 -0400 Subject: [PATCH 198/258] Use a different workaround for supporting noinit_adaptor in C++03 --- include/boost/core/allocator_access.hpp | 66 +++++++++---------------- include/boost/core/noinit_adaptor.hpp | 2 + test/allocator_construct_test.cpp | 16 ------ test/allocator_destroy_n_test.cpp | 52 ++++++++++++++++--- test/allocator_destroy_test.cpp | 4 ++ 5 files changed, 72 insertions(+), 68 deletions(-) diff --git a/include/boost/core/allocator_access.hpp b/include/boost/core/allocator_access.hpp index 7717ba0..567b448 100644 --- a/include/boost/core/allocator_access.hpp +++ b/include/boost/core/allocator_access.hpp @@ -430,30 +430,15 @@ allocator_allocate(A& a, typename allocator_size_type::type n, namespace detail { #if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct alloc_no { - char x, y; +template +struct alloc_has_construct { + BOOST_STATIC_CONSTEXPR bool value = false; }; -template -class alloc_has_construct { - template - static alloc_no - check(int); - - template - static alloc_no - check(int); - - template - static alloc_no - check(int); - - template - static char check(long); - -public: - static const bool value = sizeof(check(0)) > 1; +template +struct alloc_has_construct::type> { + BOOST_STATIC_CONSTEXPR bool value = true; }; #else template @@ -483,16 +468,14 @@ struct alloc_if { #if defined(BOOST_NO_CXX11_ALLOCATOR) template -inline typename detail::alloc_if::value>::type +inline typename detail::alloc_if::value>::type allocator_construct(A& a, T* p) { a.construct(p); } template -inline typename detail::alloc_if::value>::type +inline typename detail::alloc_if::value>::type allocator_construct(A&, T* p) { ::new((void*)p) T(); @@ -550,25 +533,15 @@ allocator_construct(A&, T* p, Args&&... args) namespace detail { #if defined(BOOST_NO_CXX11_ALLOCATOR) +template +struct alloc_has_destroy { + BOOST_STATIC_CONSTEXPR bool value = false; +}; + template -class alloc_has_destroy { - template - static alloc_no - check(int); - - template - static alloc_no - check(int); - - template - static alloc_no - check(int); - - template - static char check(long); - -public: - static const bool value = sizeof(check(0)) > 1; +struct alloc_has_destroy::type> { + BOOST_STATIC_CONSTEXPR bool value = true; }; #else template @@ -605,6 +578,11 @@ allocator_destroy(A&, T* p) namespace detail { #if defined(BOOST_NO_CXX11_ALLOCATOR) +template +struct alloc_no { + char x, y; +}; + template class alloc_has_max_size { template diff --git a/include/boost/core/noinit_adaptor.hpp b/include/boost/core/noinit_adaptor.hpp index 962b6e4..623e3ea 100644 --- a/include/boost/core/noinit_adaptor.hpp +++ b/include/boost/core/noinit_adaptor.hpp @@ -15,6 +15,8 @@ namespace boost { template struct noinit_adaptor : A { + typedef void _default_construct_destroy; + template struct rebind { typedef noinit_adaptor::type> other; diff --git a/test/allocator_construct_test.cpp b/test/allocator_construct_test.cpp index 30f2d0e..2bd1db2 100644 --- a/test/allocator_construct_test.cpp +++ b/test/allocator_construct_test.cpp @@ -26,16 +26,6 @@ struct A2 { }; #endif -template -struct A3 { - typedef T value_type; - A3() { } - template - void construct(U* p) { - ::new((void*)p) U(1); - } -}; - int main() { { @@ -52,11 +42,5 @@ int main() BOOST_TEST_EQ(i, 6); } #endif - { - A3 a; - int i = 0; - boost::allocator_construct(a, &i); - BOOST_TEST_EQ(i, 1); - } return boost::report_errors(); } diff --git a/test/allocator_destroy_n_test.cpp b/test/allocator_destroy_n_test.cpp index fc19469..381cd68 100644 --- a/test/allocator_destroy_n_test.cpp +++ b/test/allocator_destroy_n_test.cpp @@ -8,23 +8,59 @@ Distributed under the Boost Software License, Version 1.0. #include #include +struct S { + static int count; + S() { + ++count; + } + S(const S&) { + ++count; + } + ~S() { + --count; + } +}; + +int S::count = 0; + template -struct A { +struct A1 { typedef T value_type; - A() { } + A1() { } +}; + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +template +struct A2 { + typedef T value_type; + A2() { } template void destroy(U* p) { *p = U(); } }; +#endif int main() { - A a; - int i[3] = { 5, 5, 5 }; - boost::allocator_destroy_n(a, &i[0], 3); - BOOST_TEST_EQ(i[0], 0); - BOOST_TEST_EQ(i[1], 0); - BOOST_TEST_EQ(i[2], 0); + { + A1 a; + S s[3]; + boost::allocator_destroy_n(a, &s[0], 3); + BOOST_TEST_EQ(S::count, 0); + ::new((void*)&s[0]) S(); + ::new((void*)&s[1]) S(); + ::new((void*)&s[2]) S(); + } +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + { + A2 a; + int i[3] = { 5, 5, 5 }; + boost::allocator_destroy_n(a, &i[0], 3); + BOOST_TEST_EQ(i[0], 0); + BOOST_TEST_EQ(i[1], 0); + BOOST_TEST_EQ(i[2], 0); + } +#endif return boost::report_errors(); } diff --git a/test/allocator_destroy_test.cpp b/test/allocator_destroy_test.cpp index 04d794e..0b5b64e 100644 --- a/test/allocator_destroy_test.cpp +++ b/test/allocator_destroy_test.cpp @@ -29,6 +29,7 @@ struct A1 { A1() { } }; +#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct A2 { typedef T value_type; @@ -38,6 +39,7 @@ struct A2 { *p = U(); } }; +#endif int main() { @@ -48,11 +50,13 @@ int main() BOOST_TEST_EQ(S::count, 0); ::new((void*)&s) S(); } +#if !defined(BOOST_NO_CXX11_ALLOCATOR) { A2 a; int i = 5; boost::allocator_destroy(a, &i); BOOST_TEST_EQ(i, 0); } +#endif return boost::report_errors(); } From 44610b65ba4adc3cd237b7e7c44c3d5182373c8f Mon Sep 17 00:00:00 2001 From: Yichen Wang <18348405+Aiee@users.noreply.github.com> Date: Tue, 19 Apr 2022 15:26:36 +0800 Subject: [PATCH 199/258] Fix typo --- include/boost/core/noncopyable.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/core/noncopyable.hpp b/include/boost/core/noncopyable.hpp index 4a4f8ba..4ec2d54 100644 --- a/include/boost/core/noncopyable.hpp +++ b/include/boost/core/noncopyable.hpp @@ -27,7 +27,7 @@ namespace noncopyable_ // protection from unintended ADL // whether a type derives from noncopyable without needing the definition // of noncopyable itself. // -// The definition of base_token is macro-guarded so that Type Trais can +// The definition of base_token is macro-guarded so that Type Traits can // define it locally without including this header, to avoid a dependency // on Core. From 1e5c86eb9d639404ba1dadd06d0ddb466e7af4b3 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Tue, 26 Apr 2022 14:10:21 -0400 Subject: [PATCH 200/258] Add tests for the C++11 alias rebind --- test/pointer_traits_rebind_test.cpp | 44 ++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/test/pointer_traits_rebind_test.cpp b/test/pointer_traits_rebind_test.cpp index 999d195..a009463 100644 --- a/test/pointer_traits_rebind_test.cpp +++ b/test/pointer_traits_rebind_test.cpp @@ -1,5 +1,5 @@ /* -Copyright 2017 Glen Joseph Fernandes +Copyright 2017-2022 Glen Joseph Fernandes (glenjofe@gmail.com) Distributed under the Boost Software License, Version 1.0. @@ -84,15 +84,49 @@ int main() BOOST_TEST_TRAIT_TRUE((boost::core::is_same, boost::pointer_traits >::rebind_to::type>)); #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + BOOST_TEST_TRAIT_TRUE((boost::core::is_same::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind >)); BOOST_TEST_TRAIT_TRUE((boost::core::is_same, boost::pointer_traits >::rebind_to::type>)); BOOST_TEST_TRAIT_TRUE((boost::core::is_same, boost::pointer_traits >::rebind_to::type>)); BOOST_TEST_TRAIT_TRUE((boost::core::is_same, boost::pointer_traits >::rebind_to::type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind >)); #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind >)); BOOST_TEST_TRAIT_TRUE((boost::core::is_same, boost::pointer_traits >::rebind_to::type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind >)); #endif BOOST_TEST_TRAIT_TRUE((boost::core::is_same, boost::pointer_traits >::rebind_to::type>)); @@ -102,6 +136,14 @@ int main() boost::pointer_traits >::rebind_to::type>)); BOOST_TEST_TRAIT_TRUE((boost::core::is_same, boost::pointer_traits >::rebind_to::type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind >)); #endif return boost::report_errors(); } From d74140983da3379d08f0a0bfc3dd36fc6d452100 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Tue, 26 Apr 2022 14:11:31 -0400 Subject: [PATCH 201/258] Correct definition of C++11 alias rebind --- include/boost/core/pointer_traits.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/core/pointer_traits.hpp b/include/boost/core/pointer_traits.hpp index 71c9df6..fbc76e7 100644 --- a/include/boost/core/pointer_traits.hpp +++ b/include/boost/core/pointer_traits.hpp @@ -219,7 +219,7 @@ struct pointer_traits #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) template - using rebind = typename rebind_to::type*; + using rebind = typename rebind_to::type; #endif }; From 001169749289209823c5f567afed1f7e8f5c1ef0 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 28 Apr 2022 20:42:48 +0300 Subject: [PATCH 202/258] Add hash_value (refs #110) --- include/boost/core/detail/string_view.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/boost/core/detail/string_view.hpp b/include/boost/core/detail/string_view.hpp index c742198..14c7edc 100644 --- a/include/boost/core/detail/string_view.hpp +++ b/include/boost/core/detail/string_view.hpp @@ -38,8 +38,12 @@ namespace boost { +// forward declaration of boost::basic_string_view from Utility template class basic_string_view; +// forward declaration of boost::hash_range from ContainerHash +template std::size_t hash_range( It, It ); + namespace core { namespace detail @@ -1161,6 +1165,11 @@ public: } #endif + + inline friend std::size_t hash_value( basic_string_view const& sv ) + { + return boost::hash_range( sv.begin(), sv.end() ); + } }; // stream inserter From 43d0da03f3bce51594c65b36f6c383d79de401e2 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 28 Apr 2022 21:28:11 +0300 Subject: [PATCH 203/258] Remove msvc-14.1 from ci.yml --- .github/workflows/ci.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0b5e823..9943db2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -461,10 +461,6 @@ jobs: cxxstd: "14" addrmd: 32,64 os: windows-2019 - - toolset: msvc-14.1 - cxxstd: "14,17,latest" - addrmd: 32,64 - os: windows-2016 - toolset: msvc-14.2 cxxstd: "14,17,20,latest" addrmd: 32,64 From 02127743240d3f9ec67d980d13916a8f1284244e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 29 Apr 2022 02:43:37 +0300 Subject: [PATCH 204/258] Avoid -Wshadow warning under g++ 4.8 --- include/boost/core/detail/string_view.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/core/detail/string_view.hpp b/include/boost/core/detail/string_view.hpp index 14c7edc..7e85aac 100644 --- a/include/boost/core/detail/string_view.hpp +++ b/include/boost/core/detail/string_view.hpp @@ -380,10 +380,10 @@ public: { } - template BOOST_CXX14_CONSTEXPR basic_string_view( Ch const* begin, End end, - typename boost::enable_if >::type* = 0 ) BOOST_NOEXCEPT: p_( begin ), n_( end - begin ) + template BOOST_CXX14_CONSTEXPR basic_string_view( Ch const* first, End last, + typename boost::enable_if >::type* = 0 ) BOOST_NOEXCEPT: p_( first ), n_( last - first ) { - BOOST_ASSERT( end - begin >= 0 ); + BOOST_ASSERT( last - first >= 0 ); } template basic_string_view( std::basic_string, A> const& str ) BOOST_NOEXCEPT: p_( str.data() ), n_( str.size() ) From 42ed795866e6472387fdb8920fb1ece6962bb432 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Fri, 13 May 2022 18:26:08 -0400 Subject: [PATCH 205/258] Remove inline friend begin and end functions --- doc/span.qbk | 8 -------- include/boost/core/span.hpp | 8 -------- test/span_test.cpp | 14 -------------- 3 files changed, 30 deletions(-) diff --git a/doc/span.qbk b/doc/span.qbk index 7d8d3e3..e2a1425 100644 --- a/doc/span.qbk +++ b/doc/span.qbk @@ -134,14 +134,6 @@ public: constexpr const_iterator cend() const noexcept; constexpr const_reverse_iterator crbegin() const noexcept; constexpr const_reverse_iterator crend() const noexcept; - - friend constexpr iterator begin(span s) noexcept { - return s.begin(); - } - - friend constexpr iterator end(span s) noexcept { - return s.end(); - } }; template diff --git a/include/boost/core/span.hpp b/include/boost/core/span.hpp index 54dafdb..cbe8556 100644 --- a/include/boost/core/span.hpp +++ b/include/boost/core/span.hpp @@ -347,14 +347,6 @@ public: return const_reverse_iterator(s_.p); } - friend constexpr iterator begin(span s) noexcept { - return s.begin(); - } - - friend constexpr iterator end(span s) noexcept { - return s.end(); - } - private: detail::span_store s_; }; diff --git a/test/span_test.cpp b/test/span_test.cpp index 1009cba..fb05778 100644 --- a/test/span_test.cpp +++ b/test/span_test.cpp @@ -362,18 +362,6 @@ void test_crend() BOOST_TEST_EQ((boost::span(&a[0], 4).crend().base()), &a[0]); } -void test_begin_span() -{ - int a[4]; - BOOST_TEST_EQ((begin(boost::span(&a[0], 4))), &a[0]); -} - -void test_end_span() -{ - int a[4]; - BOOST_TEST_EQ((end(boost::span(&a[0], 4))), &a[4]); -} - int main() { test_extent(); @@ -421,8 +409,6 @@ int main() test_cend(); test_crbegin(); test_crend(); - test_begin_span(); - test_end_span(); return boost::report_errors(); } #else From 45e5b1ebcf67ade630a3e7195fff899677465a0a Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Fri, 13 May 2022 21:33:53 -0400 Subject: [PATCH 206/258] Add test around the MSVC defect --- test/Jamfile.v2 | 1 + test/span_boost_begin_test.cpp | 37 ++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 test/span_boost_begin_test.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 71a6544..373be22 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -331,6 +331,7 @@ run span_constructible_test.cpp ; run span_deduction_guide_test.cpp ; run as_bytes_test.cpp ; run as_writable_bytes_test.cpp ; +compile span_boost_begin_test.cpp ; run splitmix64_test.cpp : : : $(pedantic-errors) ; diff --git a/test/span_boost_begin_test.cpp b/test/span_boost_begin_test.cpp new file mode 100644 index 0000000..9da849a --- /dev/null +++ b/test/span_boost_begin_test.cpp @@ -0,0 +1,37 @@ +/* +Copyright 2022 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#if !defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CXX11_DECLTYPE) +#include +#include + +namespace boost { +namespace begin_ { + +template +void begin(T&) { } + +} // begin_ + +using namespace begin_; + +} // boost + +template class boost::span; + +void function() +{ + std::vector y; + boost::begin(y); +} +#else +int main() +{ + return 0; +} +#endif From c0e2211c2b12a618c414b5114a25351f81a9edf8 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Sat, 14 May 2022 13:05:56 -0400 Subject: [PATCH 207/258] Simplify test --- test/span_boost_begin_test.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/span_boost_begin_test.cpp b/test/span_boost_begin_test.cpp index 9da849a..b7dc1e6 100644 --- a/test/span_boost_begin_test.cpp +++ b/test/span_boost_begin_test.cpp @@ -29,9 +29,4 @@ void function() std::vector y; boost::begin(y); } -#else -int main() -{ - return 0; -} #endif From f941d2e1f7f9e83db25ddff92fa9a32290ff6872 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 30 May 2022 03:00:37 +0300 Subject: [PATCH 208/258] Add tests for __int128 to type_name_test.cpp --- test/type_name_test.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/type_name_test.cpp b/test/type_name_test.cpp index 3ed453b..bac8ccd 100644 --- a/test/type_name_test.cpp +++ b/test/type_name_test.cpp @@ -82,6 +82,11 @@ int main() TEST(long long); TEST(unsigned long long); +#if defined(BOOST_HAS_INT128) + TEST(__int128); + TEST(unsigned __int128); +#endif + TEST(char); TEST(wchar_t); #if !defined(BOOST_NO_CXX11_CHAR16_T) From b6c31904685e08fb7d9524f8cae961c0bd04cf31 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 30 May 2022 04:03:18 +0300 Subject: [PATCH 209/258] Add tn_holder specializations for __int128 (avoids macOS link errors for missing typeinfo for same) --- include/boost/core/type_name.hpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/include/boost/core/type_name.hpp b/include/boost/core/type_name.hpp index 4afef1d..53c0224 100644 --- a/include/boost/core/type_name.hpp +++ b/include/boost/core/type_name.hpp @@ -305,6 +305,26 @@ template<> struct tn_holder } }; +#if defined(BOOST_HAS_INT128) + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "__int128" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "unsigned __int128" + suffix; + } +}; + +#endif + template<> struct tn_holder { static std::string type_name( std::string const& suffix ) From ac9d79992e0f5bcdb8953330c67fe9c706c9f79f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 24 Jun 2022 14:09:47 +0300 Subject: [PATCH 210/258] Update ci.yml --- .github/workflows/ci.yml | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9943db2..9d860eb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -99,17 +99,18 @@ jobs: os: ubuntu-20.04 install: - g++-11 - sources: - - "ppa:ubuntu-toolchain-r/test" + - toolset: gcc-12 + cxxstd: "03,11,14,17,20" + os: ubuntu-22.04 + install: + - g++-12 - name: UBSAN - toolset: gcc-11 + toolset: gcc-12 cxxstd: "03,11,14,17,20" ubsan: 1 - os: ubuntu-20.04 + os: ubuntu-22.04 install: - - g++-11 - sources: - - "ppa:ubuntu-toolchain-r/test" + - g++-12 # Linux, clang - toolset: clang @@ -216,13 +217,15 @@ jobs: - toolset: clang compiler: clang++-13 cxxstd: "03,11,14,17,20" - os: ubuntu-20.04 + os: ubuntu-22.04 install: - clang-13 - sources: - - "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-13 main" - source_keys: - - "https://apt.llvm.org/llvm-snapshot.gpg.key" + - toolset: clang + compiler: clang++-14 + cxxstd: "03,11,14,17,20" + os: ubuntu-22.04 + install: + - clang-14 - toolset: clang compiler: clang++-13 cxxstd: "03,11,14,17,20" @@ -528,6 +531,7 @@ jobs: include: - os: ubuntu-18.04 - os: ubuntu-20.04 + - os: ubuntu-22.04 - os: macos-10.15 runs-on: ${{matrix.os}} @@ -574,6 +578,7 @@ jobs: include: - os: ubuntu-18.04 - os: ubuntu-20.04 + - os: ubuntu-22.04 - os: macos-10.15 runs-on: ${{matrix.os}} @@ -630,6 +635,7 @@ jobs: include: - os: ubuntu-18.04 - os: ubuntu-20.04 + - os: ubuntu-22.04 - os: macos-10.15 runs-on: ${{matrix.os}} From 7100c05490ab286b4dded94c00dd05896baa5bf8 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Sun, 17 Jul 2022 09:47:38 -0400 Subject: [PATCH 211/258] In C++03 use rebind::other instead of rebind --- include/boost/core/pointer_traits.hpp | 8 ++++++++ test/pointer_traits_rebind_sfinae_test.cpp | 2 +- test/pointer_traits_sfinae_test.cpp | 9 ++++++++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/include/boost/core/pointer_traits.hpp b/include/boost/core/pointer_traits.hpp index fbc76e7..7de7a8e 100644 --- a/include/boost/core/pointer_traits.hpp +++ b/include/boost/core/pointer_traits.hpp @@ -100,11 +100,19 @@ template struct ptr_rebind : ptr_transform { }; +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) template struct ptr_rebind >::type> { typedef typename T::template rebind type; }; +#else +template +struct ptr_rebind::other>::type> { + typedef typename T::template rebind::other type; +}; +#endif #if !defined(BOOST_NO_CXX11_DECLTYPE_N3276) template diff --git a/test/pointer_traits_rebind_sfinae_test.cpp b/test/pointer_traits_rebind_sfinae_test.cpp index d6ad087..8c7a1eb 100644 --- a/test/pointer_traits_rebind_sfinae_test.cpp +++ b/test/pointer_traits_rebind_sfinae_test.cpp @@ -56,7 +56,7 @@ struct P3 { typedef int element_type; template - struct rebind { }; + using rebind = P3; }; template diff --git a/test/pointer_traits_sfinae_test.cpp b/test/pointer_traits_sfinae_test.cpp index a7ae787..45c00d8 100644 --- a/test/pointer_traits_sfinae_test.cpp +++ b/test/pointer_traits_sfinae_test.cpp @@ -64,8 +64,15 @@ struct P2 { struct P3 { typedef int element_type; +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) template - struct rebind { }; + using rebind = P3; +#else + template + struct rebind { + typedef P3 other; + }; +#endif }; template From 8503c536dc38da4bda16a2c70e27bfe045b535d4 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Sun, 17 Jul 2022 17:18:54 -0400 Subject: [PATCH 212/258] Add documentation for rebind C++03 compatibility --- doc/pointer_traits.qbk | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/pointer_traits.qbk b/doc/pointer_traits.qbk index ce0d7b8..8b052c0 100644 --- a/doc/pointer_traits.qbk +++ b/doc/pointer_traits.qbk @@ -113,6 +113,9 @@ also not defined (`pointer_traits` is SFINAE-friendly). where `Args` is zero or more type arguments; otherwise, the member is not defined.]]] +[note When C++11 template aliases are not supported, the `type` for `rebind` is +`T::rebind::other` if such a type exists.] + [endsect] [section Member functions] From 38937b0fa33ad80a55e0c429d4cdfae9838be194 Mon Sep 17 00:00:00 2001 From: Baoshuo Ren Date: Mon, 25 Jul 2022 14:35:22 +0800 Subject: [PATCH 213/258] chore: bump macos runner version GitHub Action is sunsetting the macOS 10.15 Actions runner. It will stop working intermittently until being completely removed by 2022-8-30: https://github.blog/changelog/2022-07-20-github-actions-the-macos-10-15-actions-runner-image-is-being-deprecated-and-will-be-removed-by-8-30-22 --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9d860eb..ae6f755 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -255,7 +255,7 @@ jobs: - toolset: clang cxxstd: "03,11,14,17,2a" - os: macos-10.15 + os: macos-11 timeout-minutes: 120 runs-on: ${{matrix.os}} @@ -532,7 +532,7 @@ jobs: - os: ubuntu-18.04 - os: ubuntu-20.04 - os: ubuntu-22.04 - - os: macos-10.15 + - os: macos-11 runs-on: ${{matrix.os}} @@ -579,7 +579,7 @@ jobs: - os: ubuntu-18.04 - os: ubuntu-20.04 - os: ubuntu-22.04 - - os: macos-10.15 + - os: macos-11 runs-on: ${{matrix.os}} @@ -636,7 +636,7 @@ jobs: - os: ubuntu-18.04 - os: ubuntu-20.04 - os: ubuntu-22.04 - - os: macos-10.15 + - os: macos-11 runs-on: ${{matrix.os}} From e3745b20727e73b4b4575f9efadd53eadc4d0969 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Sat, 6 Aug 2022 18:53:40 -0400 Subject: [PATCH 214/258] Add constexpr support to empty_value --- include/boost/core/empty_value.hpp | 32 +++++++------- test/Jamfile.v2 | 1 + test/empty_value_constexpr_test.cpp | 65 +++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 16 deletions(-) create mode 100644 test/empty_value_constexpr_test.cpp diff --git a/include/boost/core/empty_value.hpp b/include/boost/core/empty_value.hpp index 9dfd442..d8ffa30 100644 --- a/include/boost/core/empty_value.hpp +++ b/include/boost/core/empty_value.hpp @@ -56,37 +56,37 @@ public: #if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) empty_value() = default; #else - empty_value() { } + BOOST_CONSTEXPR empty_value() { } #endif - empty_value(boost::empty_init_t) + BOOST_CONSTEXPR empty_value(boost::empty_init_t) : value_() { } #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) template - empty_value(boost::empty_init_t, U&& value, Args&&... args) + BOOST_CONSTEXPR empty_value(boost::empty_init_t, U&& value, Args&&... args) : value_(std::forward(value), std::forward(args)...) { } #else template - empty_value(boost::empty_init_t, U&& value) + BOOST_CONSTEXPR empty_value(boost::empty_init_t, U&& value) : value_(std::forward(value)) { } #endif #else template - empty_value(boost::empty_init_t, const U& value) + BOOST_CONSTEXPR empty_value(boost::empty_init_t, const U& value) : value_(value) { } template - empty_value(boost::empty_init_t, U& value) + BOOST_CONSTEXPR empty_value(boost::empty_init_t, U& value) : value_(value) { } #endif - const T& get() const BOOST_NOEXCEPT { + BOOST_CONSTEXPR const T& get() const BOOST_NOEXCEPT { return value_; } - T& get() BOOST_NOEXCEPT { + BOOST_CXX14_CONSTEXPR T& get() BOOST_NOEXCEPT { return value_; } @@ -104,37 +104,37 @@ public: #if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) empty_value() = default; #else - empty_value() { } + BOOST_CONSTEXPR empty_value() { } #endif - empty_value(boost::empty_init_t) + BOOST_CONSTEXPR empty_value(boost::empty_init_t) : T() { } #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) template - empty_value(boost::empty_init_t, U&& value, Args&&... args) + BOOST_CONSTEXPR empty_value(boost::empty_init_t, U&& value, Args&&... args) : T(std::forward(value), std::forward(args)...) { } #else template - empty_value(boost::empty_init_t, U&& value) + BOOST_CONSTEXPR empty_value(boost::empty_init_t, U&& value) : T(std::forward(value)) { } #endif #else template - empty_value(boost::empty_init_t, const U& value) + BOOST_CONSTEXPR empty_value(boost::empty_init_t, const U& value) : T(value) { } template - empty_value(boost::empty_init_t, U& value) + BOOST_CONSTEXPR empty_value(boost::empty_init_t, U& value) : T(value) { } #endif - const T& get() const BOOST_NOEXCEPT { + BOOST_CONSTEXPR const T& get() const BOOST_NOEXCEPT { return *this; } - T& get() BOOST_NOEXCEPT { + BOOST_CXX14_CONSTEXPR T& get() BOOST_NOEXCEPT { return *this; } }; diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 373be22..3ce6b00 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -203,6 +203,7 @@ compile first_scalar_constexpr_test.cpp ; run empty_value_test.cpp ; run empty_value_size_test.cpp ; run empty_value_final_test.cpp ; +run empty_value_constexpr_test.cpp ; run quick_exit_test.cpp ; run-fail quick_exit_fail.cpp ; diff --git a/test/empty_value_constexpr_test.cpp b/test/empty_value_constexpr_test.cpp new file mode 100644 index 0000000..f05e314 --- /dev/null +++ b/test/empty_value_constexpr_test.cpp @@ -0,0 +1,65 @@ +/* +Copyright 2022 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#if !defined(BOOST_NO_CXX11_CONSTEXPR) +#include +#include + +struct empty { + constexpr int value() const { + return 1; + } +}; + +class type { +public: + explicit constexpr type(int count) + : value_(count) { } + + constexpr int value() const { + return value_; + } + +private: + int value_; +}; + +void test_int() +{ + constexpr boost::empty_value v(boost::empty_init_t(), 4); + constexpr int c = v.get(); + BOOST_TEST_EQ(c, 4); +} + +void test_empty() +{ + constexpr boost::empty_value v = boost::empty_init_t(); + constexpr int c = v.get().value(); + BOOST_TEST_EQ(c, 1); +} + +void test_type() +{ + constexpr boost::empty_value v(boost::empty_init_t(), 2); + constexpr int c = v.get().value(); + BOOST_TEST_EQ(c, 2); +} + +int main() +{ + test_int(); + test_empty(); + test_type(); + return boost::report_errors(); +} +#else +int main() +{ + return 0; +} +#endif From 48bc47cce2fac306600424261198bac849726bd7 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Sat, 6 Aug 2022 21:24:09 -0400 Subject: [PATCH 215/258] Update empty_value docs --- doc/empty_value.qbk | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/doc/empty_value.qbk b/doc/empty_value.qbk index f693aeb..ef82f20 100644 --- a/doc/empty_value.qbk +++ b/doc/empty_value.qbk @@ -90,11 +90,11 @@ public: empty_value() = default; template - empty_value(empty_init_t, Args&&... args); + constepxr empty_value(empty_init_t, Args&&... args); - const T& get() const noexcept; + constepxr const T& get() const noexcept; - T& get() noexcept; + constepxr T& get() noexcept; }; inline constexpr empty_init_t empty_init{ }; @@ -121,8 +121,9 @@ inline constexpr empty_init_t empty_init{ }; [section Constructors] [variablelist -[[`empty_value() = default;`][Default initialize the value]] -[[`template empty_value(empty_init_t, Args&&... args);`] +[[`constepxr empty_value() = default;`][Default initialize the value]] +[[`template +constepxr empty_value(empty_init_t, Args&&... args);`] [Initialize the value with `std::forward(args)...`]]] [endsect] @@ -130,8 +131,8 @@ inline constexpr empty_init_t empty_init{ }; [section Member functions] [variablelist -[[`const T& get() const noexcept;`][Returns the value]] -[[`T& get() noexcept;`][Returns the value]]] +[[`constepxr const T& get() const noexcept;`][Returns the value]] +[[`constepxr T& get() noexcept;`][Returns the value]]] [endsect] From ab23246301bb54be1647a52b60a995fd24128a15 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 14 Aug 2022 14:24:08 +0300 Subject: [PATCH 216/258] Replaced ubuntu-18.04 GHA CI images with containers. Also use ubuntu-latest image for jobs that are running in a container. --- .github/workflows/ci.yml | 53 ++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ae6f755..b9beae4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,5 +1,5 @@ # Copyright 2020-2021 Peter Dimov -# Copyright 2021 Andrey Semashev +# Copyright 2021-2022 Andrey Semashev # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) @@ -32,7 +32,7 @@ jobs: # Linux, gcc - toolset: gcc-4.4 cxxstd: "98,0x" - os: ubuntu-20.04 + os: ubuntu-latest container: ubuntu:16.04 install: - g++-4.4 @@ -40,7 +40,7 @@ jobs: - "ppa:ubuntu-toolchain-r/test" - toolset: gcc-4.6 cxxstd: "03,0x" - os: ubuntu-20.04 + os: ubuntu-latest container: ubuntu:16.04 install: - g++-4.6 @@ -48,45 +48,50 @@ jobs: - "ppa:ubuntu-toolchain-r/test" - toolset: gcc-4.7 cxxstd: "03,11" - os: ubuntu-20.04 + os: ubuntu-latest container: ubuntu:16.04 install: - g++-4.7 - toolset: gcc-4.8 cxxstd: "03,11" - os: ubuntu-18.04 + os: ubuntu-latest + container: ubuntu:18.04 install: - g++-4.8 - toolset: gcc-4.9 cxxstd: "03,11" - os: ubuntu-20.04 + os: ubuntu-latest container: ubuntu:16.04 install: - g++-4.9 - toolset: gcc-5 cxxstd: "03,11,14,1z" - os: ubuntu-20.04 + os: ubuntu-latest container: ubuntu:16.04 install: - g++-5 - toolset: gcc-6 cxxstd: "03,11,14,1z" - os: ubuntu-18.04 + os: ubuntu-latest + container: ubuntu:18.04 install: - g++-6 - toolset: gcc-7 cxxstd: "03,11,14,17" - os: ubuntu-18.04 + os: ubuntu-latest + container: ubuntu:18.04 install: - g++-7 - toolset: gcc-8 cxxstd: "03,11,14,17,2a" - os: ubuntu-18.04 + os: ubuntu-latest + container: ubuntu:18.04 install: - g++-8 - toolset: gcc-9 cxxstd: "03,11,14,17,2a" - os: ubuntu-18.04 + os: ubuntu-latest + container: ubuntu:18.04 install: - g++-9 - toolset: gcc-10 @@ -116,66 +121,72 @@ jobs: - toolset: clang compiler: clang++-3.5 cxxstd: "03,11" - os: ubuntu-20.04 + os: ubuntu-latest container: ubuntu:16.04 install: - clang-3.5 - toolset: clang compiler: clang++-3.6 cxxstd: "03,11,14" - os: ubuntu-20.04 + os: ubuntu-latest container: ubuntu:16.04 install: - clang-3.6 - toolset: clang compiler: clang++-3.7 cxxstd: "03,11,14" - os: ubuntu-20.04 + os: ubuntu-latest container: ubuntu:16.04 install: - clang-3.7 - toolset: clang compiler: clang++-3.8 cxxstd: "03,11,14" - os: ubuntu-20.04 + os: ubuntu-latest container: ubuntu:16.04 install: - clang-3.8 - toolset: clang compiler: clang++-3.9 cxxstd: "03,11,14" - os: ubuntu-18.04 + os: ubuntu-latest + container: ubuntu:18.04 install: - clang-3.9 - toolset: clang compiler: clang++-4.0 cxxstd: "03,11,14" - os: ubuntu-18.04 + os: ubuntu-latest + container: ubuntu:18.04 install: - clang-4.0 - toolset: clang compiler: clang++-5.0 cxxstd: "03,11,14,1z" - os: ubuntu-18.04 + os: ubuntu-latest + container: ubuntu:18.04 install: - clang-5.0 - toolset: clang compiler: clang++-6.0 cxxstd: "03,11,14,17" - os: ubuntu-18.04 + os: ubuntu-latest + container: ubuntu:18.04 install: - clang-6.0 - toolset: clang compiler: clang++-7 cxxstd: "03,11,14,17" - os: ubuntu-18.04 + os: ubuntu-latest + container: ubuntu:18.04 install: - clang-7 # Note: clang-8 does not fully support C++20, so it is not compatible with libstdc++-8 in this mode - toolset: clang compiler: clang++-8 cxxstd: "03,11,14,17,2a" - os: ubuntu-18.04 + os: ubuntu-latest + container: ubuntu:18.04 install: - clang-8 - g++-7 From 1b3a9073948c1c0c492367492fb159bfab6b8139 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 14 Aug 2022 17:51:54 +0300 Subject: [PATCH 217/258] Switched gcc-9 to ubuntu-20.04 GHA CI image. --- .github/workflows/ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b9beae4..ea65f70 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -90,8 +90,7 @@ jobs: - g++-8 - toolset: gcc-9 cxxstd: "03,11,14,17,2a" - os: ubuntu-latest - container: ubuntu:18.04 + os: ubuntu-20.04 install: - g++-9 - toolset: gcc-10 From 414dfb466878af427d33b36e6ccf84d21c0e081b Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 14 Aug 2022 18:27:48 +0300 Subject: [PATCH 218/258] Removed ubuntu-18.04 image from CMake tests in GHA config as this image is deprecated. --- .github/workflows/ci.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ea65f70..9080fb7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -539,7 +539,6 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-18.04 - os: ubuntu-20.04 - os: ubuntu-22.04 - os: macos-11 @@ -586,7 +585,6 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-18.04 - os: ubuntu-20.04 - os: ubuntu-22.04 - os: macos-11 @@ -643,7 +641,6 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-18.04 - os: ubuntu-20.04 - os: ubuntu-22.04 - os: macos-11 From 68f8f36b04885fd13519ff5db49bd7cec62c6256 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 10 Sep 2022 00:55:04 +0300 Subject: [PATCH 219/258] GitHub Actions config update. - Added clang-15 jobs. - Added C++23 testing for gcc and clang on Linux. - Updated clang version for UBSAN job. - Removed clang-12 libc++ job - libc++ is now tested with clang-15. - Updated Ubuntu version for clang jobs to avoid having to use external APT repository. - Updated python package installation for compatibility with Ubuntu 22.04. --- .github/workflows/ci.yml | 72 ++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9080fb7..174be40 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -99,18 +99,18 @@ jobs: install: - g++-10 - toolset: gcc-11 - cxxstd: "03,11,14,17,20" - os: ubuntu-20.04 + cxxstd: "03,11,14,17,20,23" + os: ubuntu-22.04 install: - g++-11 - toolset: gcc-12 - cxxstd: "03,11,14,17,20" + cxxstd: "03,11,14,17,20,23" os: ubuntu-22.04 install: - g++-12 - name: UBSAN toolset: gcc-12 - cxxstd: "03,11,14,17,20" + cxxstd: "03,11,14,17,20,23" ubsan: 1 os: ubuntu-22.04 install: @@ -205,63 +205,63 @@ jobs: - toolset: clang compiler: clang++-11 cxxstd: "03,11,14,17,20" - os: ubuntu-20.04 + os: ubuntu-22.04 install: - clang-11 - toolset: clang compiler: clang++-12 - cxxstd: "03,11,14,17,20" - os: ubuntu-20.04 + cxxstd: "03,11,14,17,20,2b" + os: ubuntu-22.04 install: - clang-12 - - toolset: clang - compiler: clang++-12 - cxxstd: "03,11,14,17,20" - cxxflags: -stdlib=libc++ - linkflags: -stdlib=libc++ - os: ubuntu-20.04 - install: - - clang-12 - - libc++-12-dev - - libc++abi-12-dev - toolset: clang compiler: clang++-13 - cxxstd: "03,11,14,17,20" + cxxstd: "03,11,14,17,20,2b" os: ubuntu-22.04 install: - clang-13 - toolset: clang compiler: clang++-14 - cxxstd: "03,11,14,17,20" + cxxstd: "03,11,14,17,20,2b" os: ubuntu-22.04 install: - clang-14 - toolset: clang - compiler: clang++-13 - cxxstd: "03,11,14,17,20" - os: ubuntu-20.04 + compiler: clang++-15 + cxxstd: "03,11,14,17,20,2b" + os: ubuntu-22.04 install: - - clang-13 - - libc++-13-dev - - libc++abi-13-dev + - clang-15 sources: - - "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-13 main" + - "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-15 main" + source_keys: + - "https://apt.llvm.org/llvm-snapshot.gpg.key" + - toolset: clang + compiler: clang++-15 + cxxstd: "03,11,14,17,20,2b" + os: ubuntu-22.04 + install: + - clang-15 + - libc++-15-dev + - libc++abi-15-dev + sources: + - "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-15 main" source_keys: - "https://apt.llvm.org/llvm-snapshot.gpg.key" cxxflags: -stdlib=libc++ linkflags: -stdlib=libc++ - name: UBSAN toolset: clang - compiler: clang++-12 - cxxstd: "03,11,14,17,20" + compiler: clang++-14 + cxxstd: "03,11,14,17,20,2b" cxxflags: -stdlib=libc++ linkflags: -stdlib=libc++ ubsan: 1 - os: ubuntu-20.04 + os: ubuntu-22.04 install: - - clang-12 - - libc++-12-dev - - libc++abi-12-dev + - clang-14 + - libc++-14-dev + - libc++abi-14-dev - toolset: clang cxxstd: "03,11,14,17,2a" @@ -285,7 +285,13 @@ jobs: if [ -f "/etc/debian_version" ] then apt-get -o Acquire::Retries=$NET_RETRY_COUNT update - apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y sudo software-properties-common tzdata wget curl apt-transport-https ca-certificates make build-essential g++ python python3 perl git cmake + if [ "$(apt-cache search "^python-is-python3$" | wc -l)" -ne 0 ] + then + PYTHON_PACKAGE="python-is-python3" + else + PYTHON_PACKAGE="python" + fi + apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y sudo software-properties-common tzdata wget curl apt-transport-https ca-certificates make build-essential g++ $PYTHON_PACKAGE python3 perl git cmake fi fi git config --global pack.threads 0 From 162a4e1d24d1cab4f24cbca9489203d891f352e6 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 10 Sep 2022 02:49:25 +0300 Subject: [PATCH 220/258] Disabled warnings about deprecated builtins on clang-15. The warnings are caused by Boost.TypeTraits: https://github.com/boostorg/type_traits/issues/173 --- test/Jamfile.v2 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 3ce6b00..5cdcb61 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -14,6 +14,8 @@ project : requirements extra msvc:on clang:on + # https://github.com/boostorg/type_traits/issues/173 + clang-15:-Wno-deprecated-builtins gcc:on gcc-4.4:-Wno-sign-compare ; From 1fa592c9ec5878d4f22ca349fa60ef159c4a23dc Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 18 Sep 2022 13:53:55 +0300 Subject: [PATCH 221/258] Add a deleted constructor from nullptr_t to string_view; closes #113 --- include/boost/core/detail/string_view.hpp | 16 ++++++++++++++++ test/Jamfile.v2 | 2 ++ test/sv_nullptr_fail.cpp | 10 ++++++++++ 3 files changed, 28 insertions(+) create mode 100644 test/sv_nullptr_fail.cpp diff --git a/include/boost/core/detail/string_view.hpp b/include/boost/core/detail/string_view.hpp index 7e85aac..5a1f6c8 100644 --- a/include/boost/core/detail/string_view.hpp +++ b/include/boost/core/detail/string_view.hpp @@ -403,6 +403,22 @@ public: { } +#if !defined(BOOST_NO_CXX11_NULLPTR) +# if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) + + basic_string_view( std::nullptr_t ) = delete; + +# else + +private: + + basic_string_view( std::nullptr_t ); + +public: + +# endif +#endif + // BOOST_CONSTEXPR basic_string_view& operator=( basic_string_view const& ) BOOST_NOEXCEPT & = default; // conversions diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 5cdcb61..94b465e 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -327,6 +327,8 @@ run sv_conversion_test2.cpp : ; run sv_common_reference_test.cpp ; compile sv_common_reference_test2.cpp ; compile sv_windows_h_test.cpp ; +compile-fail sv_nullptr_fail.cpp + : $(warning-as-errors-off) ; run span_test.cpp ; run span_types_test.cpp ; diff --git a/test/sv_nullptr_fail.cpp b/test/sv_nullptr_fail.cpp new file mode 100644 index 0000000..2afbcd0 --- /dev/null +++ b/test/sv_nullptr_fail.cpp @@ -0,0 +1,10 @@ +// Copyright 2022 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include + +int main() +{ + return boost::core::string_view( nullptr ).size() == 0; +} From 0ac87736f86d04fda4d628bc4a55a53447c8e135 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 18 Sep 2022 21:10:18 +0300 Subject: [PATCH 222/258] Explicitly disable sv_nullptr_fail when BOOST_NO_CXX11_NULLPTR is defined, because libc++ seems to have nullptr even in C++03 mode --- test/sv_nullptr_fail.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/sv_nullptr_fail.cpp b/test/sv_nullptr_fail.cpp index 2afbcd0..d862038 100644 --- a/test/sv_nullptr_fail.cpp +++ b/test/sv_nullptr_fail.cpp @@ -3,8 +3,17 @@ // https://www.boost.org/LICENSE_1_0.txt #include +#include + +#if defined(BOOST_NO_CXX11_NULLPTR) + +#error BOOST_NO_CXX11_NULLPTR is defined, test will be skipped. + +#else int main() { return boost::core::string_view( nullptr ).size() == 0; } + +#endif From 89852794ca9d4a2d3fd439dfa3d20bca11f7988b Mon Sep 17 00:00:00 2001 From: tocic Date: Mon, 19 Sep 2022 12:53:00 +0300 Subject: [PATCH 223/258] Fix typos in docs (#127) * Fix typos in docs Use "Acknowledgments" everywhere for consistency. * amend! Fix typos in docs Fix typos in docs Use "Acknowledgements" everywhere for consistency. --- doc/allocator_access.qbk | 2 +- doc/demangle.qbk | 2 +- doc/enable_if.qbk | 4 ++-- doc/ignore_unused.qbk | 2 +- doc/pointer_traits.qbk | 4 ++-- doc/ref.qbk | 2 +- doc/scoped_enum.qbk | 4 ++-- doc/use_default.qbk | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/doc/allocator_access.qbk b/doc/allocator_access.qbk index 1a0c82f..afde7d3 100644 --- a/doc/allocator_access.qbk +++ b/doc/allocator_access.qbk @@ -293,7 +293,7 @@ returns `a`.]]] [endsect] -[section Acknowledgments] +[section Acknowledgements] Glen Fernandes implemented the allocator access utilities. diff --git a/doc/demangle.qbk b/doc/demangle.qbk index 16bd65e..cd0febc 100644 --- a/doc/demangle.qbk +++ b/doc/demangle.qbk @@ -125,7 +125,7 @@ return `nullptr` if demangling failed. [endsect] -[section Acknowledgments] +[section Acknowledgements] The implementation of `core::demangle` was taken from `boost/exception/detail/type_info.hpp`, which in turn was adapted diff --git a/doc/enable_if.qbk b/doc/enable_if.qbk index a64a2b1..6562d0b 100644 --- a/doc/enable_if.qbk +++ b/doc/enable_if.qbk @@ -304,8 +304,8 @@ depends on the template arguments of the class. Note that again, the second argument to `enable_if` is not needed; the default (`void`) is the correct value. -The `enable_if_has_type` template is usable this scenario but instead of -using a type traits to enable or disable a specialization, it use a +The `enable_if_has_type` template is usable in this scenario but instead of +using a type trait to enable or disable a specialization, it uses a SFINAE context to check for the existence of a dependent type inside its parameter. For example, the following structure extracts a dependent `value_type` from T if and only if `T::value_type` exists. diff --git a/doc/ignore_unused.qbk b/doc/ignore_unused.qbk index e3bdc4c..bd018e8 100644 --- a/doc/ignore_unused.qbk +++ b/doc/ignore_unused.qbk @@ -51,7 +51,7 @@ int fun( int foo, int bar ) [endsect] -[section Acknowledgments] +[section Acknowledgements] `boost::ignore_unused()` was contributed by Adam Wulkiewicz. diff --git a/doc/pointer_traits.qbk b/doc/pointer_traits.qbk index 8b052c0..fb846b8 100644 --- a/doc/pointer_traits.qbk +++ b/doc/pointer_traits.qbk @@ -124,7 +124,7 @@ also not defined (`pointer_traits` is SFINAE-friendly). [[`static pointer pointer_traits::pointer_to(element_type& v);`] [[variablelist [[Remark] -[If `element_type` is a void type, or if `T::pointer_to(v)` is not well formed, +[If `element_type` is a void type, or if `T::pointer_to(v)` is not well-formed, this member is not defined.]] [[Returns] [A pointer to `v` obtained by calling `T::pointer_to(v)`.]]]]] @@ -165,7 +165,7 @@ also not defined (`pointer_traits` is SFINAE-friendly). [endsect] -[section Acknowledgments] +[section Acknowledgements] Glen Fernandes implemented `pointer_traits` and `to_address` with reviews and guidance from Peter Dimov. diff --git a/doc/ref.qbk b/doc/ref.qbk index 454851b..3614497 100644 --- a/doc/ref.qbk +++ b/doc/ref.qbk @@ -68,7 +68,7 @@ The type-expression `boost::unwrap_reference::type` is [xinclude ref_reference.xml] -[section Acknowledgments] +[section Acknowledgements] `ref` and `cref` were originally part of the Tuple library by Jaakko J\u00E4rvi. They were "promoted to `boost::` status" by diff --git a/doc/scoped_enum.qbk b/doc/scoped_enum.qbk index a9e95f4..4c06f97 100644 --- a/doc/scoped_enum.qbk +++ b/doc/scoped_enum.qbk @@ -46,7 +46,7 @@ The user can portably declare such enumeration as follows: } BOOST_SCOPED_ENUM_DECLARE_END(future_errc) -These macros allows to use `future_errc` in almost all the cases as an scoped enum. +These macros allow using `future_errc` in almost all the cases as a scoped enum. future_errc ev = future_errc::no_state; @@ -179,7 +179,7 @@ such cases. [endsect] -[section Acknowledgments] +[section Acknowledgements] This scoped enum emulation was developed by Beman Dawes, Vicente J. Botet Escriba and Anthony Williams. diff --git a/doc/use_default.qbk b/doc/use_default.qbk index 2149161..63328ef 100644 --- a/doc/use_default.qbk +++ b/doc/use_default.qbk @@ -11,7 +11,7 @@ Distributed under the Boost Software License, Version 1.0. [section Overview] The header provides the type `boost::use_default` -which is used by other Boost libraries as a sentinel type in a templates to +which is used by other Boost libraries as a sentinel type in templates to indicate defaults. [endsect] From 3510f6244b28be2b2f9fcba416db2d80cae496a6 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Wed, 21 Sep 2022 02:19:11 +0300 Subject: [PATCH 224/258] Added fclose_deleter. fclose_deleter can be used as a deleter function object for std::FILE pointers returned by std::fopen. --- doc/core.qbk | 1 + doc/fclose_deleter.qbk | 34 ++++++++++++++++++ include/boost/core/fclose_deleter.hpp | 45 +++++++++++++++++++++++ test/Jamfile.v2 | 3 ++ test/fclose_deleter_test.cpp | 52 +++++++++++++++++++++++++++ test/quick.cpp | 1 + 6 files changed, 136 insertions(+) create mode 100644 doc/fclose_deleter.qbk create mode 100644 include/boost/core/fclose_deleter.hpp create mode 100644 test/fclose_deleter_test.cpp diff --git a/doc/core.qbk b/doc/core.qbk index fd677c4..8e2d1a3 100644 --- a/doc/core.qbk +++ b/doc/core.qbk @@ -60,6 +60,7 @@ criteria for inclusion is that the utility component be: [include noinit_adaptor.qbk] [include noncopyable.qbk] [include null_deleter.qbk] +[include fclose_deleter.qbk] [include nvp.qbk] [include pointer_traits.qbk] [include quick_exit.qbk] diff --git a/doc/fclose_deleter.qbk b/doc/fclose_deleter.qbk new file mode 100644 index 0000000..30dd913 --- /dev/null +++ b/doc/fclose_deleter.qbk @@ -0,0 +1,34 @@ +[/ + / Copyright (c) 2022 Andrey Semashev + / + / Distributed under the Boost Software License, Version 1.0. (See accompanying + / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:fclose_deleter fclose_deleter] + +[simplesect Authors] + +* Andrey Semashev + +[endsimplesect] + +[section Header ] + +The header `` defines the `boost::fclose_deleter` function object, +which can be used as a deleter with smart pointers such as `unique_ptr` or `shared_ptr` pointing to `std::FILE`. +structures returned by `std::fopen` calls. The deleter calls `std::fclose` on the passed pointer, causing +the file stream to be flushed and closed. + +[section Example] +`` +std::unique_ptr< std::FILE, boost::fclose_deleter > make_file(const char* filename, const char* open_mode) +{ + return { std::fopen(filename, open_mode) }; +} +`` +[endsect] + +[endsect] + +[endsect] diff --git a/include/boost/core/fclose_deleter.hpp b/include/boost/core/fclose_deleter.hpp new file mode 100644 index 0000000..7a0d34a --- /dev/null +++ b/include/boost/core/fclose_deleter.hpp @@ -0,0 +1,45 @@ +/* + * Copyright Andrey Semashev 2022. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ +/*! + * \file fclose_deleter.hpp + * \author Andrey Semashev + * \date 21.09.2022 + * + * This header contains an \c fclose_deleter implementation. This is a deleter + * function object that invokes std::fclose on the passed pointer to + * a std::FILE structure. + */ + +#ifndef BOOST_CORE_FCLOSE_DELETER_HPP +#define BOOST_CORE_FCLOSE_DELETER_HPP + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +//! A function object that closes a file +struct fclose_deleter +{ + //! Function object result type + typedef void result_type; + /*! + * Closes the file handle + */ + void operator() (std::FILE* p) const BOOST_NOEXCEPT + { + std::fclose(p); + } +}; + +} // namespace boost + +#endif // BOOST_CORE_FCLOSE_DELETER_HPP diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 94b465e..a601332 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -186,6 +186,9 @@ compile-fail scoped_enum_compile_fail_conv_to_int.cpp run underlying_type.cpp ; +compile fclose_deleter_test.cpp + : windows:_CRT_SECURE_NO_WARNINGS windows:_CRT_SECURE_NO_DEPRECATE ; + run pointer_traits_pointer_test.cpp ; run pointer_traits_element_type_test.cpp ; run pointer_traits_difference_type_test.cpp ; diff --git a/test/fclose_deleter_test.cpp b/test/fclose_deleter_test.cpp new file mode 100644 index 0000000..dbe85a5 --- /dev/null +++ b/test/fclose_deleter_test.cpp @@ -0,0 +1,52 @@ +/* + * Copyright Andrey Semashev 2022. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ +/*! + * \file fclose_deleter_test.cpp + * \author Andrey Semashev + * \date 21.09.2022 + * + * This file contains tests for \c boost::fclose_deleter. + */ + +#include +#include +#include +#include +#if !defined(BOOST_NO_CXX11_SMART_PTR) +#include +#endif + +#if !defined(BOOST_NO_CXX11_SMART_PTR) +std::unique_ptr< std::FILE, boost::fclose_deleter > make_unique_file(const char* filename) +{ + return std::unique_ptr< std::FILE, boost::fclose_deleter >(std::fopen(filename, "w")); +} + +std::shared_ptr< std::FILE > make_shared_file(const char* filename) +{ + return std::shared_ptr< std::FILE >(std::fopen(filename, "w"), boost::fclose_deleter()); +} +#endif + +int main() +{ + const char* const filename = "fcd_test.txt"; + + std::FILE* file = std::fopen(filename, "w"); + if (file) + { + boost::fclose_deleter()(file); + file = NULL; + } + +#if !defined(BOOST_NO_CXX11_SMART_PTR) + make_unique_file(filename); + make_shared_file(filename); +#endif + + std::remove(filename); +} diff --git a/test/quick.cpp b/test/quick.cpp index f82d77b..fdfe983 100644 --- a/test/quick.cpp +++ b/test/quick.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include From 00f4f11f14fd993d343292331f7bcd494c668dec Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Wed, 21 Sep 2022 18:09:42 +0300 Subject: [PATCH 225/258] Added a check for NULL pointer in fclose_deleter. The deleter can be called on a null pointer by shared_ptr. Also added tests with unique_ptr from Boost.Move and shared_ptr from Boost.SmartPtr. --- include/boost/core/fclose_deleter.hpp | 3 ++- test/Jamfile.v2 | 6 +++--- test/fclose_deleter_test.cpp | 29 +++++++++++++++++++++++---- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/include/boost/core/fclose_deleter.hpp b/include/boost/core/fclose_deleter.hpp index 7a0d34a..8f7a7fd 100644 --- a/include/boost/core/fclose_deleter.hpp +++ b/include/boost/core/fclose_deleter.hpp @@ -36,7 +36,8 @@ struct fclose_deleter */ void operator() (std::FILE* p) const BOOST_NOEXCEPT { - std::fclose(p); + if (BOOST_LIKELY(!!p)) + std::fclose(p); } }; diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index a601332..a08c937 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -176,7 +176,7 @@ run demangle_test.cpp run demangled_name_test.cpp : : : always_show_run_output ; -run demangled_name_test.cpp : : : off always_show_run_output : demangled_name_test_no_rtti ; +run demangled_name_test.cpp : : : off always_show_run_output : demangled_name_test_no_rtti ; run scoped_enum.cpp ; compile-fail scoped_enum_compile_fail_conv_from_int.cpp @@ -186,8 +186,8 @@ compile-fail scoped_enum_compile_fail_conv_to_int.cpp run underlying_type.cpp ; -compile fclose_deleter_test.cpp - : windows:_CRT_SECURE_NO_WARNINGS windows:_CRT_SECURE_NO_DEPRECATE ; +run fclose_deleter_test.cpp + : : : windows:_CRT_SECURE_NO_WARNINGS windows:_CRT_SECURE_NO_DEPRECATE ; run pointer_traits_pointer_test.cpp ; run pointer_traits_element_type_test.cpp ; diff --git a/test/fclose_deleter_test.cpp b/test/fclose_deleter_test.cpp index dbe85a5..4363335 100644 --- a/test/fclose_deleter_test.cpp +++ b/test/fclose_deleter_test.cpp @@ -16,17 +16,29 @@ #include #include #include +#include +#include #if !defined(BOOST_NO_CXX11_SMART_PTR) #include #endif +boost::movelib::unique_ptr< std::FILE, boost::fclose_deleter > make_boost_unique_file(const char* filename) +{ + return boost::movelib::unique_ptr< std::FILE, boost::fclose_deleter >(std::fopen(filename, "w")); +} + +boost::shared_ptr< std::FILE > make_boost_shared_file(const char* filename) +{ + return boost::shared_ptr< std::FILE >(std::fopen(filename, "w"), boost::fclose_deleter()); +} + #if !defined(BOOST_NO_CXX11_SMART_PTR) -std::unique_ptr< std::FILE, boost::fclose_deleter > make_unique_file(const char* filename) +std::unique_ptr< std::FILE, boost::fclose_deleter > make_std_unique_file(const char* filename) { return std::unique_ptr< std::FILE, boost::fclose_deleter >(std::fopen(filename, "w")); } -std::shared_ptr< std::FILE > make_shared_file(const char* filename) +std::shared_ptr< std::FILE > make_std_shared_file(const char* filename) { return std::shared_ptr< std::FILE >(std::fopen(filename, "w"), boost::fclose_deleter()); } @@ -43,9 +55,18 @@ int main() file = NULL; } + make_boost_unique_file(filename); + make_boost_shared_file(filename); + #if !defined(BOOST_NO_CXX11_SMART_PTR) - make_unique_file(filename); - make_shared_file(filename); + make_std_unique_file(filename); + make_std_shared_file(filename); +#endif + + // Test if the deleter can be called on a NULL pointer + boost::shared_ptr< std::FILE >(static_cast< std::FILE* >(NULL), boost::fclose_deleter()); +#if !defined(BOOST_NO_CXX11_SMART_PTR) + std::shared_ptr< std::FILE >(static_cast< std::FILE* >(NULL), boost::fclose_deleter()); #endif std::remove(filename); From 2cc3e234478f160fc467839fbb20f1ae3a369a8f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 21 Sep 2022 18:55:31 +0300 Subject: [PATCH 226/258] Add test/bit_width_fail (refs #129) --- test/Jamfile.v2 | 3 +++ test/bit_width_fail.cpp | 13 +++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 test/bit_width_fail.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index a601332..29003c1 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -299,6 +299,9 @@ run bit_popcount_test.cpp run bit_endian_test.cpp : : : $(pedantic-errors) ; +compile-fail bit_width_fail.cpp + : off ; + run type_name_test.cpp ; run sv_types_test.cpp ; diff --git a/test/bit_width_fail.cpp b/test/bit_width_fail.cpp new file mode 100644 index 0000000..9e76000 --- /dev/null +++ b/test/bit_width_fail.cpp @@ -0,0 +1,13 @@ +// Negative test for boost/core/bit.hpp (bit_width) +// +// Copyright 2022 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include + +int main() +{ + // should fail, because 0 is a signed integral type + return boost::core::bit_width( 0 ); +} From 66a742f41e4d197eb8e2aef4aef64c275e9700f0 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 21 Sep 2022 19:07:33 +0300 Subject: [PATCH 227/258] Statically assert the unsigned integer requirements in bit.hpp. Fixes #129. --- include/boost/core/bit.hpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/include/boost/core/bit.hpp b/include/boost/core/bit.hpp index ddd435b..69e1763 100644 --- a/include/boost/core/bit.hpp +++ b/include/boost/core/bit.hpp @@ -92,6 +92,8 @@ BOOST_CONSTEXPR inline int countl_impl( boost::ulong_long_type x ) BOOST_NOEXCEP template BOOST_CONSTEXPR int countl_zero( T x ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + return boost::core::detail::countl_impl( x ); } @@ -169,6 +171,8 @@ inline int countl_impl( boost::uint16_t x ) BOOST_NOEXCEPT template int countl_zero( T x ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + BOOST_STATIC_ASSERT( sizeof(T) == sizeof(boost::uint8_t) || sizeof(T) == sizeof(boost::uint16_t) || sizeof(T) == sizeof(boost::uint32_t) || sizeof(T) == sizeof(boost::uint64_t) ); BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint8_t) ) @@ -194,6 +198,8 @@ int countl_zero( T x ) BOOST_NOEXCEPT template BOOST_CONSTEXPR int countl_one( T x ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + return boost::core::countl_zero( static_cast( ~x ) ); } @@ -234,6 +240,8 @@ BOOST_CONSTEXPR inline int countr_impl( boost::ulong_long_type x ) BOOST_NOEXCEP template BOOST_CONSTEXPR int countr_zero( T x ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + return boost::core::detail::countr_impl( x ); } @@ -304,6 +312,8 @@ inline int countr_impl( boost::uint16_t x ) BOOST_NOEXCEPT template int countr_zero( T x ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + BOOST_STATIC_ASSERT( sizeof(T) == sizeof(boost::uint8_t) || sizeof(T) == sizeof(boost::uint16_t) || sizeof(T) == sizeof(boost::uint32_t) || sizeof(T) == sizeof(boost::uint64_t) ); BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint8_t) ) @@ -329,6 +339,8 @@ int countr_zero( T x ) BOOST_NOEXCEPT template BOOST_CONSTEXPR int countr_one( T x ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + return boost::core::countr_zero( static_cast( ~x ) ); } @@ -377,6 +389,8 @@ BOOST_CORE_POPCOUNT_CONSTEXPR inline int popcount_impl( boost::ulong_long_type x template BOOST_CONSTEXPR int popcount( T x ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + return boost::core::detail::popcount_impl( x ); } @@ -408,6 +422,8 @@ BOOST_CXX14_CONSTEXPR inline int popcount_impl( boost::uint64_t x ) BOOST_NOEXCE template BOOST_CXX14_CONSTEXPR int popcount( T x ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + BOOST_STATIC_ASSERT( sizeof(T) <= sizeof(boost::uint64_t) ); BOOST_IF_CONSTEXPR ( sizeof(T) <= sizeof(boost::uint32_t) ) @@ -427,6 +443,8 @@ BOOST_CXX14_CONSTEXPR int popcount( T x ) BOOST_NOEXCEPT template BOOST_CXX14_CONSTEXPR T rotl( T x, int s ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + unsigned const mask = std::numeric_limits::digits - 1; return x << (s & mask) | x >> ((-s) & mask); } @@ -434,6 +452,8 @@ BOOST_CXX14_CONSTEXPR T rotl( T x, int s ) BOOST_NOEXCEPT template BOOST_CXX14_CONSTEXPR T rotr( T x, int s ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + unsigned const mask = std::numeric_limits::digits - 1; return x >> (s & mask) | x << ((-s) & mask); } @@ -443,6 +463,8 @@ BOOST_CXX14_CONSTEXPR T rotr( T x, int s ) BOOST_NOEXCEPT template BOOST_CONSTEXPR bool has_single_bit( T x ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + return x != 0 && ( x & ( x - 1 ) ) == 0; } @@ -451,6 +473,8 @@ BOOST_CONSTEXPR bool has_single_bit( T x ) BOOST_NOEXCEPT template BOOST_CONSTEXPR T bit_width( T x ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + return static_cast( std::numeric_limits::digits - boost::core::countl_zero( x ) ); } @@ -458,6 +482,8 @@ BOOST_CONSTEXPR T bit_width( T x ) BOOST_NOEXCEPT template BOOST_CONSTEXPR T bit_floor( T x ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + return x == 0? 0: T(1) << ( boost::core::bit_width( x ) - 1 ); } @@ -510,6 +536,8 @@ BOOST_CXX14_CONSTEXPR inline boost::uint64_t bit_ceil_impl( boost::uint64_t x ) template BOOST_CXX14_CONSTEXPR T bit_ceil( T x ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + BOOST_STATIC_ASSERT( sizeof(T) <= sizeof(boost::uint64_t) ); BOOST_IF_CONSTEXPR ( sizeof(T) <= sizeof(boost::uint32_t) ) From 860eed6baf29f5ff75cdb98b456c6d273d93b96e Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Wed, 21 Sep 2022 19:19:38 +0300 Subject: [PATCH 228/258] Use depinst to install library dependencies in GHA config. --- .github/workflows/ci.yml | 46 ++++++++++++---------------------------- 1 file changed, 14 insertions(+), 32 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 174be40..f3b58cf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -383,6 +383,7 @@ jobs: BUILD_JOBS=$((nproc || sysctl -n hw.ncpu) 2> /dev/null) echo "BUILD_JOBS=$BUILD_JOBS" >> $GITHUB_ENV echo "CMAKE_BUILD_PARALLEL_LEVEL=$BUILD_JOBS" >> $GITHUB_ENV + DEPINST_ARGS=() GIT_VERSION="$(git --version | sed -e 's/git version //')" GIT_HAS_JOBS=1 if [ -f "/etc/debian_version" ] @@ -409,25 +410,16 @@ jobs: fi if [ "$GIT_HAS_JOBS" -ne 0 ] then - GIT_ARGS="--jobs $GIT_FETCH_JOBS" + DEPINST_ARGS+=("--git_args" "--jobs $GIT_FETCH_JOBS") fi cd .. git clone -b "$BOOST_BRANCH" --depth 1 "https://github.com/boostorg/boost.git" "boost-root" cd boost-root mkdir -p libs/$LIBRARY cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY - git submodule init tools/boost_install - git submodule init libs/headers - git submodule init tools/build - git submodule init tools/cmake - git submodule init libs/assert - git submodule init libs/config - git submodule init libs/static_assert - git submodule init libs/throw_exception - git submodule init libs/type_traits - git submodule init libs/utility - git submodule init libs/io - git submodule update $GIT_ARGS + git submodule update --init tools/boostdep + DEPINST_ARGS+=("$LIBRARY") + python tools/boostdep/depinst/depinst.py "${DEPINST_ARGS[@]}" ./bootstrap.sh ./b2 headers if [ -n "${{matrix.compiler}}" -o -n "$GCC_TOOLCHAIN_ROOT" ] @@ -519,18 +511,8 @@ jobs: git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root cd boost-root xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\ - git submodule init tools/boost_install - git submodule init libs/headers - git submodule init tools/build - git submodule init tools/cmake - git submodule init libs/assert - git submodule init libs/config - git submodule init libs/static_assert - git submodule init libs/throw_exception - git submodule init libs/type_traits - git submodule init libs/utility - git submodule init libs/io - git submodule update --jobs %GIT_FETCH_JOBS% + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs %GIT_FETCH_JOBS%" %LIBRARY% cmd /c bootstrap b2 -d0 headers @@ -569,14 +551,14 @@ jobs: REF=${GITHUB_BASE_REF:-$GITHUB_REF} REF=${REF#refs/heads/} echo REF: $REF - BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true + BOOST_BRANCH=develop && [ "$REF" = "master" ] && BOOST_BRANCH=master || true echo BOOST_BRANCH: $BOOST_BRANCH cd .. git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root cd boost-root cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY git submodule update --init tools/boostdep - python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + python tools/boostdep/depinst/depinst.py --git_args "--jobs $GIT_FETCH_JOBS" $LIBRARY - name: Use library with add_subdirectory run: | @@ -615,17 +597,17 @@ jobs: REF=${GITHUB_BASE_REF:-$GITHUB_REF} REF=${REF#refs/heads/} echo REF: $REF - BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true + BOOST_BRANCH=develop && [ "$REF" = "master" ] && BOOST_BRANCH=master || true echo BOOST_BRANCH: $BOOST_BRANCH cd .. git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root cd boost-root cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY git submodule update --init tools/boostdep - python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + python tools/boostdep/depinst/depinst.py --git_args "--jobs $GIT_FETCH_JOBS" $LIBRARY - name: Configure - run: | + run: cd ../boost-root mkdir __build__ && cd __build__ cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DCMAKE_INSTALL_PREFIX=~/.local .. @@ -671,14 +653,14 @@ jobs: REF=${GITHUB_BASE_REF:-$GITHUB_REF} REF=${REF#refs/heads/} echo REF: $REF - BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true + BOOST_BRANCH=develop && [ "$REF" = "master" ] && BOOST_BRANCH=master || true echo BOOST_BRANCH: $BOOST_BRANCH cd .. git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root cd boost-root cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY git submodule update --init tools/boostdep - python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + python tools/boostdep/depinst/depinst.py --git_args "--jobs $GIT_FETCH_JOBS" $LIBRARY - name: Configure run: | From a7f76af262f3af0699781d33ea5e19b2275545db Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Wed, 21 Sep 2022 20:00:03 +0300 Subject: [PATCH 229/258] Fixed unintentional change to CMake configure step in GHA config. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f3b58cf..6169ea4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -607,7 +607,7 @@ jobs: python tools/boostdep/depinst/depinst.py --git_args "--jobs $GIT_FETCH_JOBS" $LIBRARY - name: Configure - run: + run: | cd ../boost-root mkdir __build__ && cd __build__ cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DCMAKE_INSTALL_PREFIX=~/.local .. From fd615f3bfeba7fabe175fde813d76ed33390bb5d Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Wed, 21 Sep 2022 19:54:35 +0300 Subject: [PATCH 230/258] Use depinst in AppVeyor CI as well. --- appveyor.yml | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index b894436..ae3ed65 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -60,24 +60,15 @@ environment: CXXSTD: 03,11,14,1z install: + - set GIT_FETCH_JOBS=8 - set BOOST_BRANCH=develop - if "%APPVEYOR_REPO_BRANCH%" == "master" set BOOST_BRANCH=master - cd .. - git clone -b %BOOST_BRANCH% https://github.com/boostorg/boost.git boost-root - cd boost-root - - git submodule init libs/headers - - git submodule init libs/assert - - git submodule init libs/config - - git submodule init libs/predef - - git submodule init libs/static_assert - - git submodule init libs/throw_exception - - git submodule init libs/type_traits - - git submodule init libs/utility - - git submodule init libs/io - - git submodule init tools/build - - git submodule init tools/boost_install - - git submodule update --jobs 4 + - git submodule update --init tools/boostdep - xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\core\ + - python tools/boostdep/depinst/depinst.py --git_args "--jobs %GIT_FETCH_JOBS%" core - cmd /c bootstrap - b2 headers From 9cbf3ac420c0b54996197198e900be338dbc3d05 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Wed, 21 Sep 2022 21:05:27 +0300 Subject: [PATCH 231/258] Fixed fclose_deleter test failing to build with CMake. Jamfile parser created incorrect test for fclose_deleter_test, which resulted in a compiler error. Prevent the parser from creating the test target by reformatting the Jamfile and create a CMake target with proper dependencies. --- test/CMakeLists.txt | 4 ++++ test/Jamfile.v2 | 3 +-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7524ae6..21350f5 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -27,6 +27,10 @@ set(BOOST_TEST_LINK_LIBRARIES Boost::core Boost::utility) boost_test(TYPE run SOURCES sv_conversion_test2.cpp) +set(BOOST_TEST_LINK_LIBRARIES Boost::core Boost::move Boost::smart_ptr) + +boost_test(TYPE run SOURCES fclose_deleter_test.cpp) + endif() add_subdirectory(swap) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index a08c937..5f356da 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -186,8 +186,7 @@ compile-fail scoped_enum_compile_fail_conv_to_int.cpp run underlying_type.cpp ; -run fclose_deleter_test.cpp - : : : windows:_CRT_SECURE_NO_WARNINGS windows:_CRT_SECURE_NO_DEPRECATE ; +run fclose_deleter_test.cpp : : : windows:_CRT_SECURE_NO_WARNINGS windows:_CRT_SECURE_NO_DEPRECATE ; run pointer_traits_pointer_test.cpp ; run pointer_traits_element_type_test.cpp ; From 09f2aa123ac4ef2598ef167ab10ced5fa9ea7517 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Wed, 21 Sep 2022 21:14:13 +0300 Subject: [PATCH 232/258] Enabled parallel build in CMake CI jobs. --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6169ea4..7ca3a58 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -565,7 +565,7 @@ jobs: cd ../boost-root/libs/$LIBRARY/test/cmake_subdir_test mkdir __build__ && cd __build__ cmake .. - cmake --build . + cmake --build . -- -j $BUILD_JOBS ctest --output-on-failure --no-tests=error posix-cmake-install: @@ -615,13 +615,13 @@ jobs: - name: Install run: | cd ../boost-root/__build__ - cmake --build . --target install + cmake --build . --target install -- -j $BUILD_JOBS - name: Use the installed library run: | cd ../boost-root/libs/$LIBRARY/test/cmake_install_test && mkdir __build__ && cd __build__ cmake -DCMAKE_INSTALL_PREFIX=~/.local .. - cmake --build . + cmake --build . -- -j $BUILD_JOBS ctest --output-on-failure --no-tests=error posix-cmake-test: @@ -671,7 +671,7 @@ jobs: - name: Build tests run: | cd ../boost-root/__build__ - cmake --build . --target tests + cmake --build . --target tests -- -j $BUILD_JOBS - name: Run tests run: | From 1c79871f0f29261f92f281a35505f6ab8dcc281f Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Wed, 21 Sep 2022 21:20:40 +0300 Subject: [PATCH 233/258] Added dependency on Boost.Config to fclose_deleter_test CMake target. --- test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 21350f5..5521551 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -27,7 +27,7 @@ set(BOOST_TEST_LINK_LIBRARIES Boost::core Boost::utility) boost_test(TYPE run SOURCES sv_conversion_test2.cpp) -set(BOOST_TEST_LINK_LIBRARIES Boost::core Boost::move Boost::smart_ptr) +set(BOOST_TEST_LINK_LIBRARIES Boost::core Boost::config Boost::move Boost::smart_ptr) boost_test(TYPE run SOURCES fclose_deleter_test.cpp) From b407b5d87df30f75ca501c1b6f2930c0913d4ca7 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 22 Sep 2022 01:31:01 +0300 Subject: [PATCH 234/258] Change bit_width to return `int`, LWG3656 has been applied as a DR to C++20 --- doc/bit.qbk | 4 ++-- include/boost/core/bit.hpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/bit.qbk b/doc/bit.qbk index e8d5fce..81b9536 100644 --- a/doc/bit.qbk +++ b/doc/bit.qbk @@ -45,7 +45,7 @@ template constexpr T bit_floor(T x) noexcept; template -constexpr T bit_width(T x) noexcept; +constexpr int bit_width(T x) noexcept; // Rotating @@ -119,7 +119,7 @@ constant expression context. * *Requires:* `T` must be an unsigned integer type. * *Returns:* If `x == 0`, 0; otherwise the maximal value `y` such that `has_single_bit(y)` is `true` and `y <= x`. -`template constexpr T bit_width(T x) noexcept;` +`template constexpr int bit_width(T x) noexcept;` * *Requires:* `T` must be an unsigned integer type. * *Returns:* If `x == 0`, 0; otherwise one plus the base-2 logarithm of `x`, with any fractional part discarded. diff --git a/include/boost/core/bit.hpp b/include/boost/core/bit.hpp index 69e1763..5d14685 100644 --- a/include/boost/core/bit.hpp +++ b/include/boost/core/bit.hpp @@ -468,15 +468,15 @@ BOOST_CONSTEXPR bool has_single_bit( T x ) BOOST_NOEXCEPT return x != 0 && ( x & ( x - 1 ) ) == 0; } -// bit_width should return int, https://cplusplus.github.io/LWG/issue3656 +// bit_width returns `int` now, https://cplusplus.github.io/LWG/issue3656 +// has been applied to C++20 as a DR template -BOOST_CONSTEXPR T bit_width( T x ) BOOST_NOEXCEPT +BOOST_CONSTEXPR int bit_width( T x ) BOOST_NOEXCEPT { BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); - return static_cast( - std::numeric_limits::digits - boost::core::countl_zero( x ) ); + return std::numeric_limits::digits - boost::core::countl_zero( x ); } template From 65377a2e13b81487c165769e9eab0a7c4b9059bb Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Tue, 18 Oct 2022 17:55:59 +0300 Subject: [PATCH 235/258] Updated to GHA checkout@v3 to avoid deprecation warnings. --- .github/workflows/ci.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7ca3a58..3ea3c78 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -296,7 +296,7 @@ jobs: fi git config --global pack.threads 0 - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install packages if: matrix.install @@ -492,7 +492,7 @@ jobs: runs-on: ${{matrix.os}} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup Boost shell: cmd @@ -534,7 +534,7 @@ jobs: runs-on: ${{matrix.os}} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install packages if: matrix.install @@ -580,7 +580,7 @@ jobs: runs-on: ${{matrix.os}} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install packages if: matrix.install @@ -636,7 +636,7 @@ jobs: runs-on: ${{matrix.os}} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install packages if: matrix.install From 5e95d28eb6163a16aff70055d93cf7ff619f19ab Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 1 Dec 2022 13:59:17 +0200 Subject: [PATCH 236/258] Update revision history --- doc/changes.qbk | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/doc/changes.qbk b/doc/changes.qbk index a11f7e1..3036f24 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -6,11 +6,25 @@ [section Revision History] +[section Changes in 1.80.0] + +* `empty_value` members are now marked as `constexpr`. +* Added `fclose_deleter`, a deleter that calls `std::fclose` on a pointer to `std::FILE`. +* Bit manipulation utilities in `boost/core/bit.hpp` now explicitly require unsigned integers on input. + ([@https://github.com/boostorg/core/issues/129 #129]) +* `bit_width` now returns `int` instead of a value of the input argument type. This follows the + resolution of [@https://cplusplus.github.io/LWG/issue3656 LWG3656]. + +[endsect] + [section Changes in 1.79.0] * Added `boost::allocator_traits`, an implementation of `std::allocator_traits`. * Made `boost::pointer_traits` SFINAE friendly. -* `boost/iterator.hpp` is deprecated and will be removed in a future release. The header defines `boost::iterator` template, which is equivalent to `std::iterator` in `` header. However, since `std::iterator` is itself deprecated in C++17, users are advised to remove `boost::iterator` or `std::iterator` use from their code. +* `boost/iterator.hpp` is deprecated and will be removed in a future release. The header defines the + `boost::iterator` template, which is equivalent to `std::iterator` in the `` header. However, + since `std::iterator` is itself deprecated in C++17, users are advised to remove the use of `boost::iterator` + or `std::iterator` from their code. * Added `boost::core::verbose_terminate_handler`, a utility function intended to be passed to `std::set_terminate` that prints information about the uncaught exception to `stderr`. From a67ec1f75cb0201dd9a242a4797c8ae21bcc36c8 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 4 Dec 2022 02:02:40 +0300 Subject: [PATCH 237/258] Corrected Boost release version, added links in changelog. --- doc/changes.qbk | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/changes.qbk b/doc/changes.qbk index 3036f24..a9b550a 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -6,11 +6,11 @@ [section Revision History] -[section Changes in 1.80.0] +[section Changes in 1.81.0] -* `empty_value` members are now marked as `constexpr`. -* Added `fclose_deleter`, a deleter that calls `std::fclose` on a pointer to `std::FILE`. -* Bit manipulation utilities in `boost/core/bit.hpp` now explicitly require unsigned integers on input. +* [link core.empty_value `empty_value`] members are now marked as `constexpr`. +* Added [link core.fclose_deleter `fclose_deleter`], a deleter that calls `std::fclose` on a pointer to `std::FILE`. +* Bit manipulation utilities in [link core.bit `boost/core/bit.hpp`] now explicitly require unsigned integers on input. ([@https://github.com/boostorg/core/issues/129 #129]) * `bit_width` now returns `int` instead of a value of the input argument type. This follows the resolution of [@https://cplusplus.github.io/LWG/issue3656 LWG3656]. From ad20fadde7daead18e882722e095e4137b4f417d Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 4 Dec 2022 03:52:31 +0300 Subject: [PATCH 238/258] Added missing release notes for Boost 1.80.0. --- doc/changes.qbk | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/doc/changes.qbk b/doc/changes.qbk index a9b550a..fc10bcd 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -17,6 +17,20 @@ [endsect] +[section Changes in 1.80.0] + +* In [link core.allocator_access `boost/core/allocator_access.hpp`], added detection of `construct` and `destroy` + members of an allocator. +* `boost/core/alloc_construct.hpp` header is now deprecated and will be removed in a future release. Its functionality + was moved to [link core.allocator_access `boost/core/allocator_access.hpp`]. In particular, new methods + `allocator_construct_n` and `allocator_destroy_n` were added for allocating and destroying arrays. +* Worked around MSVC bug that failed to compile [link core.span `span`] in C++17 mode when Boost.Range headers were included. + ([@https://github.com/boostorg/core/issues/105 #105], [@https://github.com/boostorg/core/pull/115 PR#115]) +* Added support for 128-bit integer types in [link core.type_name `type_name`]. +* In [link core.pointer_traits `pointer_traits`], pointer rebinding now supports C++03 compilers. + +[endsect] + [section Changes in 1.79.0] * Added `boost::allocator_traits`, an implementation of `std::allocator_traits`. From 3eaba7afc06004128d44da2c464a41423cf6168d Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 5 Dec 2022 20:34:46 -0800 Subject: [PATCH 239/258] Fix for sprintf deprecation warning --- include/boost/core/lightweight_test.hpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/include/boost/core/lightweight_test.hpp b/include/boost/core/lightweight_test.hpp index 3b5df89..4f10fd4 100644 --- a/include/boost/core/lightweight_test.hpp +++ b/include/boost/core/lightweight_test.hpp @@ -202,6 +202,14 @@ inline unsigned long test_output_impl( char32_t const& v ) { return v; } #pragma warning(disable: 4996) #endif +// Use snprintf if available as some complilers (clang 14.0) issue deprecation warnings for sprintf +#if ( defined(_MSC_VER) && _MSC_VER < 1900 ) || ( defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) ) || \ + ( defined(__cplusplus) && __cplusplus < 201103L) +# define BOOST_CORE_SNPRINTF(buffer, format, arg) std::sprintf(buffer, format, arg) +#else +# define BOOST_CORE_SNPRINTF(buffer, format, arg) std::snprintf(buffer, sizeof(buffer)/sizeof(buffer[0]), format, arg) +#endif + inline std::string test_output_impl( char const& v ) { if( std::isprint( static_cast( v ) ) ) @@ -211,7 +219,7 @@ inline std::string test_output_impl( char const& v ) else { char buffer[ 8 ]; - std::sprintf( buffer, "\\x%02X", static_cast( v ) ); + BOOST_CORE_SNPRINTF( buffer, "\\x%02X", static_cast( v ) ); return buffer; } From db916e4673569b64e9a222244433102c9de741f6 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 6 Dec 2022 08:10:14 -0800 Subject: [PATCH 240/258] Correct test macro and add undef --- include/boost/core/lightweight_test.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/boost/core/lightweight_test.hpp b/include/boost/core/lightweight_test.hpp index 4f10fd4..b321a84 100644 --- a/include/boost/core/lightweight_test.hpp +++ b/include/boost/core/lightweight_test.hpp @@ -202,9 +202,8 @@ inline unsigned long test_output_impl( char32_t const& v ) { return v; } #pragma warning(disable: 4996) #endif -// Use snprintf if available as some complilers (clang 14.0) issue deprecation warnings for sprintf -#if ( defined(_MSC_VER) && _MSC_VER < 1900 ) || ( defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) ) || \ - ( defined(__cplusplus) && __cplusplus < 201103L) +// Use snprintf if available as some compilers (clang 14.0) issue deprecation warnings for sprintf +#if ( defined(_MSC_VER) && _MSC_VER < 1900 ) || ( defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) ) # define BOOST_CORE_SNPRINTF(buffer, format, arg) std::sprintf(buffer, format, arg) #else # define BOOST_CORE_SNPRINTF(buffer, format, arg) std::snprintf(buffer, sizeof(buffer)/sizeof(buffer[0]), format, arg) @@ -225,6 +224,8 @@ inline std::string test_output_impl( char const& v ) } } +#undef BOOST_CORE_SNPRINTF + #if defined(_MSC_VER) #pragma warning(pop) #endif From d5b7c3c0dc25b43163af87deeb30cef2491a2f58 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 6 Dec 2022 08:11:22 -0800 Subject: [PATCH 241/258] Add snprintf macro --- include/boost/core/type_name.hpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/include/boost/core/type_name.hpp b/include/boost/core/type_name.hpp index 53c0224..e39dc28 100644 --- a/include/boost/core/type_name.hpp +++ b/include/boost/core/type_name.hpp @@ -185,14 +185,23 @@ template std::string array_template_name() # pragma warning( disable: 4996 ) #endif +// Use snprintf if available as some compilers (clang 14.0) issue deprecation warnings for sprintf +#if ( defined(_MSC_VER) && _MSC_VER < 1900 ) || ( defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) ) +# define BOOST_CORE_SNPRINTF(buffer, format, arg) std::sprintf(buffer, format, arg) +#else +# define BOOST_CORE_SNPRINTF(buffer, format, arg) std::snprintf(buffer, sizeof(buffer)/sizeof(buffer[0]), format, arg) +#endif + inline std::string tn_to_string( std::size_t n ) { char buffer[ 32 ]; - std::sprintf( buffer, "%lu", static_cast< unsigned long >( n ) ); + BOOST_CORE_SNPRINTF( buffer, "%lu", static_cast< unsigned long >( n ) ); return buffer; } +#undef BOOST_CORE_SNPRINTF + #if defined(BOOST_MSVC) # pragma warning( pop ) #endif From 2778c5cca6e50537399c9639be47474c3f3193da Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 7 Dec 2022 22:33:17 +0200 Subject: [PATCH 242/258] Rename BOOST_CORE_SNPRINTF to BOOST_CORE_DETAIL_SNPRINTF --- include/boost/core/lightweight_test.hpp | 8 ++++---- include/boost/core/type_name.hpp | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/boost/core/lightweight_test.hpp b/include/boost/core/lightweight_test.hpp index b321a84..9eaf83f 100644 --- a/include/boost/core/lightweight_test.hpp +++ b/include/boost/core/lightweight_test.hpp @@ -204,9 +204,9 @@ inline unsigned long test_output_impl( char32_t const& v ) { return v; } // Use snprintf if available as some compilers (clang 14.0) issue deprecation warnings for sprintf #if ( defined(_MSC_VER) && _MSC_VER < 1900 ) || ( defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) ) -# define BOOST_CORE_SNPRINTF(buffer, format, arg) std::sprintf(buffer, format, arg) +# define BOOST_CORE_DETAIL_SNPRINTF(buffer, format, arg) std::sprintf(buffer, format, arg) #else -# define BOOST_CORE_SNPRINTF(buffer, format, arg) std::snprintf(buffer, sizeof(buffer)/sizeof(buffer[0]), format, arg) +# define BOOST_CORE_DETAIL_SNPRINTF(buffer, format, arg) std::snprintf(buffer, sizeof(buffer)/sizeof(buffer[0]), format, arg) #endif inline std::string test_output_impl( char const& v ) @@ -218,13 +218,13 @@ inline std::string test_output_impl( char const& v ) else { char buffer[ 8 ]; - BOOST_CORE_SNPRINTF( buffer, "\\x%02X", static_cast( v ) ); + BOOST_CORE_DETAIL_SNPRINTF( buffer, "\\x%02X", static_cast( v ) ); return buffer; } } -#undef BOOST_CORE_SNPRINTF +#undef BOOST_CORE_DETAIL_SNPRINTF #if defined(_MSC_VER) #pragma warning(pop) diff --git a/include/boost/core/type_name.hpp b/include/boost/core/type_name.hpp index e39dc28..21faa3c 100644 --- a/include/boost/core/type_name.hpp +++ b/include/boost/core/type_name.hpp @@ -187,20 +187,20 @@ template std::string array_template_name() // Use snprintf if available as some compilers (clang 14.0) issue deprecation warnings for sprintf #if ( defined(_MSC_VER) && _MSC_VER < 1900 ) || ( defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) ) -# define BOOST_CORE_SNPRINTF(buffer, format, arg) std::sprintf(buffer, format, arg) +# define BOOST_CORE_DETAIL_SNPRINTF(buffer, format, arg) std::sprintf(buffer, format, arg) #else -# define BOOST_CORE_SNPRINTF(buffer, format, arg) std::snprintf(buffer, sizeof(buffer)/sizeof(buffer[0]), format, arg) +# define BOOST_CORE_DETAIL_SNPRINTF(buffer, format, arg) std::snprintf(buffer, sizeof(buffer)/sizeof(buffer[0]), format, arg) #endif inline std::string tn_to_string( std::size_t n ) { char buffer[ 32 ]; - BOOST_CORE_SNPRINTF( buffer, "%lu", static_cast< unsigned long >( n ) ); + BOOST_CORE_DETAIL_SNPRINTF( buffer, "%lu", static_cast< unsigned long >( n ) ); return buffer; } -#undef BOOST_CORE_SNPRINTF +#undef BOOST_CORE_DETAIL_SNPRINTF #if defined(BOOST_MSVC) # pragma warning( pop ) From be8790115cb77c216051176b3e940ee85cb3b717 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Tue, 6 Dec 2022 21:19:11 +0300 Subject: [PATCH 243/258] Added portable snprintf/vsnprintf definition. This definitions is mostly a workaround for older MSVC versions that only provided non-portable _snprintf etc. that are not fully conforming to the standard snprintf. This implementation fixes its issues wrt. null termination and returned values in case of buffer overflows. On platforms that support the standard snprintf, the definitions in the header are equivalent to the standard functions. --- doc/changes.qbk | 8 ++ doc/core.qbk | 1 + doc/snprintf.qbk | 47 +++++++++ include/boost/core/snprintf.hpp | 173 ++++++++++++++++++++++++++++++++ test/Jamfile.v2 | 2 + test/snprintf_test.cpp | 86 ++++++++++++++++ 6 files changed, 317 insertions(+) create mode 100644 doc/snprintf.qbk create mode 100644 include/boost/core/snprintf.hpp create mode 100644 test/snprintf_test.cpp diff --git a/doc/changes.qbk b/doc/changes.qbk index fc10bcd..e314558 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -1,11 +1,19 @@ [/ Copyright 2021 Peter Dimov + Copyright 2022 Andrey Semashev Distributed under the Boost Software License, Version 1.0. https://boost.org/LICENSE_1_0.txt) ] [section Revision History] +[section Changes in 1.82.0] + +* Added [link core.snprintf `boost/core/snprintf.hpp`] header with portable definitions of `snprintf`, `vsnprintf` and + their `wchar_t` counterparts. + +[endsect] + [section Changes in 1.81.0] * [link core.empty_value `empty_value`] members are now marked as `constexpr`. diff --git a/doc/core.qbk b/doc/core.qbk index 8e2d1a3..a7943f7 100644 --- a/doc/core.qbk +++ b/doc/core.qbk @@ -70,6 +70,7 @@ criteria for inclusion is that the utility component be: [include swap.qbk] [include typeinfo.qbk] [include type_name.qbk] +[include snprintf.qbk] [include uncaught_exceptions.qbk] [include use_default.qbk] [include verbose_terminate_handler.qbk] diff --git a/doc/snprintf.qbk b/doc/snprintf.qbk new file mode 100644 index 0000000..814019a --- /dev/null +++ b/doc/snprintf.qbk @@ -0,0 +1,47 @@ +[/ + / Copyright (c) 2022 Andrey Semashev + / + / Distributed under the Boost Software License, Version 1.0. (See accompanying + / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:snprintf snprintf] + +[simplesect Authors] + +* Andrey Semashev + +[endsimplesect] + +[section Header ] + +The header `` provides portable definition of [@https://en.cppreference.com/w/c/io/fprintf `snprintf`], +`vsnprintf` and their corresponding `wchar_t` counterparts. On a platform that supports these functions in the standard library, +these definitions are equivalent to the standard functions. On other platforms (mainly, older MSVC versions) these functions +are emulated through non-standard functions that have similar behavior. + +Depending on the standard library, certain implementation differences are exposed to the user: + +* Any non-standard behavior with respect to string format description are not hidden by the emulation. +* Returned value of `boost::core::snprintf` in case if the output buffer is too small may not be equal to the number of characters + that would have been written if the buffer was large enough. It is, however, equal or larger than the buffer size, + which still allows the caller to detect the buffer overflow condition. The formatted output is still properly null-terminated + in this case. + +[note Unlike `snprintf`, `swprintf` does not return the number of characters to be written if the output buffer is too small +but returns -1 instead. Furthermore, `swprintf` may or may not produce characters in the output buffer in this case.] + +[section Example] +`` +char buf[10]; +int n = boost::core::snprintf(buf, sizeof(buf), "%d", i); +if (n < 0) + throw std::runtime_error("Formatting error"); +if (n >= sizeof(buf)) + throw std::runtime_error("Formatting buffer overflow"); +`` +[endsect] + +[endsect] + +[endsect] diff --git a/include/boost/core/snprintf.hpp b/include/boost/core/snprintf.hpp new file mode 100644 index 0000000..91e252b --- /dev/null +++ b/include/boost/core/snprintf.hpp @@ -0,0 +1,173 @@ +/* + * Copyright Andrey Semashev 2022. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ +/*! + * \file snprintf.hpp + * \author Andrey Semashev + * \date 06.12.2022 + * + * \brief The header provides more portable definition of snprintf and vsnprintf, + * as well as \c wchar_t counterparts. + */ + +#ifndef BOOST_CORE_SNPRINTF_HPP_INCLUDED_ +#define BOOST_CORE_SNPRINTF_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(__MINGW32__) + +#include +#include +#if !defined(__MINGW64_VERSION_MAJOR) +#include +#endif + +// MinGW32 and MinGW-w64 provide their own snprintf implementations that are compliant with the C standard. +#define BOOST_CORE_DETAIL_MINGW_SNPRINTF + +#elif (defined(BOOST_MSSTL_VERSION) && BOOST_MSSTL_VERSION < 140) + +#include +#include +#include + +// MSVC snprintfs are not conforming but they are good enough for typical use cases. +#define BOOST_CORE_DETAIL_MSVC_LEGACY_SNPRINTF + +#endif + +namespace boost { + +namespace core { + +#if defined(BOOST_CORE_DETAIL_MINGW_SNPRINTF) || defined(BOOST_CORE_DETAIL_MSVC_LEGACY_SNPRINTF) + +#if defined(BOOST_CORE_DETAIL_MINGW_SNPRINTF) + +inline int vsnprintf(char* buf, std::size_t size, const char* format, std::va_list args) +{ + return __mingw_vsnprintf(buf, size, format, args); +} + +inline int vswprintf(wchar_t* buf, std::size_t size, const wchar_t* format, std::va_list args) +{ +#if defined(__MINGW64_VERSION_MAJOR) + int res = __mingw_vsnwprintf(buf, size, format, args); + // __mingw_vsnwprintf returns the number of characters to be printed, but (v)swprintf is expected to return -1 on truncation + if (static_cast< unsigned int >(res) >= size) + res = -1; + return res; +#else + // Legacy MinGW32 does not provide __mingw_vsnwprintf, so use _vsnwprintf from MSVC CRT + if (BOOST_UNLIKELY(size == 0u || size > static_cast< std::size_t >(INT_MAX))) + return -1; + + int res = _vsnwprintf(buf, size, format, args); + // (v)swprintf is expected to return -1 on truncation, so we only need to ensure the output is null-terminated + if (static_cast< unsigned int >(res) >= size) + { + buf[size - 1u] = L'\0'; + res = -1; + } + + return res; +#endif +} + +#elif defined(BOOST_CORE_DETAIL_MSVC_LEGACY_SNPRINTF) + +#if defined(_MSC_VER) +#pragma warning(push) +// '_vsnprintf': This function or variable may be unsafe. Consider using _vsnprintf_s instead. +#pragma warning(disable: 4996) +#endif + +inline int vsnprintf(char* buf, std::size_t size, const char* format, std::va_list args) +{ + if (BOOST_UNLIKELY(size == 0u)) + return 0; + if (BOOST_UNLIKELY(size > static_cast< std::size_t >(INT_MAX))) + return -1; + + buf[size - 1u] = '\0'; + int res = _vsnprintf(buf, size, format, args); + if (static_cast< unsigned int >(res) >= size) + { + // _vsnprintf returns -1 if the output was truncated and in case of other errors. + // Detect truncation by checking whether the output buffer was written over entirely. + if (buf[size - 1u] != '\0') + { + buf[size - 1u] = '\0'; + res = static_cast< int >(size); + } + } + + return res; +} + +inline int vswprintf(wchar_t* buf, std::size_t size, const wchar_t* format, std::va_list args) +{ + if (BOOST_UNLIKELY(size == 0u || size > static_cast< std::size_t >(INT_MAX))) + return -1; + + int res = _vsnwprintf(buf, size, format, args); + // (v)swprintf is expected to return -1 on truncation, so we only need to ensure the output is null-terminated + if (static_cast< unsigned int >(res) >= size) + { + buf[size - 1u] = L'\0'; + res = -1; + } + + return res; +} + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +#endif + +inline int snprintf(char* buf, std::size_t size, const char* format, ...) +{ + std::va_list args; + va_start(args, format); + int res = vsnprintf(buf, size, format, args); + va_end(args); + return res; +} + +inline int swprintf(wchar_t* buf, std::size_t size, const wchar_t* format, ...) +{ + std::va_list args; + va_start(args, format); + int res = vswprintf(buf, size, format, args); + va_end(args); + return res; +} + +#else // defined(BOOST_CORE_DETAIL_MINGW_SNPRINTF) || defined(BOOST_CORE_DETAIL_MSVC_LEGACY_SNPRINTF) + +// Standard-conforming compilers already have the correct snprintfs +using ::snprintf; +using ::vsnprintf; + +using ::swprintf; +using ::vswprintf; + +#endif // defined(BOOST_CORE_DETAIL_MINGW_SNPRINTF) || defined(BOOST_CORE_DETAIL_MSVC_LEGACY_SNPRINTF) + +} // namespace core + +} // namespace boost + +#endif // BOOST_CORE_SNPRINTF_HPP_INCLUDED_ diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 63c3b9e..d51c098 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -303,6 +303,8 @@ compile-fail bit_width_fail.cpp run type_name_test.cpp ; +run snprintf_test.cpp ; + run sv_types_test.cpp ; run sv_construct_test.cpp ; run sv_iteration_test.cpp ; diff --git a/test/snprintf_test.cpp b/test/snprintf_test.cpp new file mode 100644 index 0000000..48483ba --- /dev/null +++ b/test/snprintf_test.cpp @@ -0,0 +1,86 @@ +/* + * Copyright Andrey Semashev 2022. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ +/*! + * \file snprintf_test.cpp + * \author Andrey Semashev + * \date 06.12.2022 + * + * This file contains tests for \c boost::core::snprintf. + */ + +#include +#include +#include +#include + +void test_snprintf() +{ + char buf[11]; + std::memset(buf, 0xFF, sizeof(buf)); + + std::size_t buf_size = sizeof(buf) - 1u; + + int res = boost::core::snprintf(buf, buf_size, "%s", "0123"); + BOOST_TEST_EQ(res, 4); + int cmp_res = std::memcmp(buf, "0123", sizeof("0123")); + BOOST_TEST_EQ(cmp_res, 0); + + std::memset(buf, 0xFF, sizeof(buf)); + + // Suppress compiler checks for buffer overflow + const char* volatile str = "0123456789"; + + res = boost::core::snprintf(buf, buf_size, "%s", str); + BOOST_TEST_GE(res, 10); + cmp_res = std::memcmp(buf, "012345678", sizeof("012345678")); + BOOST_TEST_EQ(cmp_res, 0); + BOOST_TEST_EQ(buf[10], static_cast< char >(~static_cast< char >(0))); + + std::memset(buf, 0xFF, sizeof(buf)); + + res = boost::core::snprintf(buf, 0, "%s", str); + BOOST_TEST_GE(res, 0); + BOOST_TEST_EQ(buf[0], static_cast< char >(~static_cast< char >(0))); +} + +void test_swprintf() +{ + wchar_t buf[11]; + std::memset(buf, 0xFF, sizeof(buf)); + + std::size_t buf_size = sizeof(buf) / sizeof(*buf) - 1u; + + int res = boost::core::swprintf(buf, buf_size, L"%ls", L"0123"); + BOOST_TEST_EQ(res, 4); + int cmp_res = std::memcmp(buf, L"0123", sizeof(L"0123")); + BOOST_TEST_EQ(cmp_res, 0); + + std::memset(buf, 0xFF, sizeof(buf)); + + // Suppress compiler checks for buffer overflow + const wchar_t* volatile str = L"0123456789"; + + res = boost::core::swprintf(buf, buf_size, L"%ls", str); + BOOST_TEST_LT(res, 0); + // swprintf may or may not write to the buffer in case of overflow. + // E.g. glibc 2.35 doesn't and libc on MacOS 11 does. + BOOST_TEST_EQ(buf[10], static_cast< wchar_t >(~static_cast< wchar_t >(0))); + + std::memset(buf, 0xFF, sizeof(buf)); + + res = boost::core::swprintf(buf, 0, L"%ls", str); + BOOST_TEST_LT(res, 0); + BOOST_TEST_EQ(buf[0], static_cast< wchar_t >(~static_cast< wchar_t >(0))); +} + +int main() +{ + test_snprintf(); + test_swprintf(); + + return boost::report_errors(); +} From d42833575851498503c29fc2cbd92d843a07d400 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Fri, 9 Dec 2022 04:15:02 +0300 Subject: [PATCH 244/258] Remove the use of snprintf for trivial formatting. This implements in-place formatting for small hex numbers instead of using snprintf with the associated portability scaffolding. This also removes the need for #include . --- include/boost/core/lightweight_test.hpp | 29 ++++++------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/include/boost/core/lightweight_test.hpp b/include/boost/core/lightweight_test.hpp index 9eaf83f..37d713d 100644 --- a/include/boost/core/lightweight_test.hpp +++ b/include/boost/core/lightweight_test.hpp @@ -32,7 +32,6 @@ #include #include #include -#include #if defined(_MSC_VER) && defined(_CPPLIB_VER) && defined(_DEBUG) # include @@ -197,18 +196,6 @@ inline unsigned long test_output_impl( char16_t const& v ) { return v; } inline unsigned long test_output_impl( char32_t const& v ) { return v; } #endif -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable: 4996) -#endif - -// Use snprintf if available as some compilers (clang 14.0) issue deprecation warnings for sprintf -#if ( defined(_MSC_VER) && _MSC_VER < 1900 ) || ( defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) ) -# define BOOST_CORE_DETAIL_SNPRINTF(buffer, format, arg) std::sprintf(buffer, format, arg) -#else -# define BOOST_CORE_DETAIL_SNPRINTF(buffer, format, arg) std::snprintf(buffer, sizeof(buffer)/sizeof(buffer[0]), format, arg) -#endif - inline std::string test_output_impl( char const& v ) { if( std::isprint( static_cast( v ) ) ) @@ -217,19 +204,17 @@ inline std::string test_output_impl( char const& v ) } else { - char buffer[ 8 ]; - BOOST_CORE_DETAIL_SNPRINTF( buffer, "\\x%02X", static_cast( v ) ); + static const char char_table[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + char buffer[ 4 ]; + buffer[ 0 ] = '\\'; + buffer[ 1 ] = 'x'; + buffer[ 2 ] = char_table[ (static_cast( v ) >> 4u) & 0x0f ]; + buffer[ 3 ] = char_table[ static_cast( v ) & 0x0f ]; - return buffer; + return std::string( buffer, 4u ); } } -#undef BOOST_CORE_DETAIL_SNPRINTF - -#if defined(_MSC_VER) -#pragma warning(pop) -#endif - // predicates struct lw_test_eq From 2286749f977e003f3ad996fef6ee50a29d8b8841 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Thu, 15 Dec 2022 01:08:51 -0500 Subject: [PATCH 245/258] Change order of restoration of warning disables in allocator access --- include/boost/core/allocator_access.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/core/allocator_access.hpp b/include/boost/core/allocator_access.hpp index 567b448..8e33ebb 100644 --- a/include/boost/core/allocator_access.hpp +++ b/include/boost/core/allocator_access.hpp @@ -807,14 +807,14 @@ using allocator_rebind_t = typename allocator_rebind::type; } /* boost */ -#if defined(_LIBCPP_SUPPRESS_DEPRECATED_POP) -_LIBCPP_SUPPRESS_DEPRECATED_POP +#if defined(_MSC_VER) +#pragma warning(pop) #endif #if defined(_STL_RESTORE_DEPRECATED_WARNING) _STL_RESTORE_DEPRECATED_WARNING #endif -#if defined(_MSC_VER) -#pragma warning(pop) +#if defined(_LIBCPP_SUPPRESS_DEPRECATED_POP) +_LIBCPP_SUPPRESS_DEPRECATED_POP #endif #endif From 75c765cc1333e7656c52feddace1f303e53419a3 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 18 Dec 2022 01:02:18 +0300 Subject: [PATCH 246/258] Removed suppression of -Wno-deprecated-builtins on clang-15. Boost.TypeTraits was updated to not use the deprecated builtins, so suppressing the warning should no longer be necessary. --- test/Jamfile.v2 | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index d51c098..bf44f47 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -14,8 +14,6 @@ project : requirements extra msvc:on clang:on - # https://github.com/boostorg/type_traits/issues/173 - clang-15:-Wno-deprecated-builtins gcc:on gcc-4.4:-Wno-sign-compare ; From 86bf1d4aeccf3327b8c7084c2a7244a3a6b78c17 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Thu, 22 Dec 2022 15:46:55 +0300 Subject: [PATCH 247/258] Deprecated boost::core::is_same and the associated header. Moved is_same implementation to detail (both directory and namespace) to use in the public headers and avoid introducing new dependencies. The documentation now recommends users to use Boost.TypeTraits or C++ standard library instead. Also, removed unnecessary includes and added missing ones in a few places. --- doc/changes.qbk | 3 + doc/is_same.qbk | 5 ++ doc/lightweight_test.qbk | 4 +- include/boost/core/detail/is_same.hpp | 39 +++++++++ include/boost/core/detail/string_view.hpp | 12 +-- include/boost/core/is_same.hpp | 25 +++--- include/boost/core/lightweight_test_trait.hpp | 6 +- include/boost/core/type_name.hpp | 1 - test/CMakeLists.txt | 2 +- test/allocator_const_pointer_test.cpp | 6 +- test/allocator_const_void_pointer_test.cpp | 6 +- test/allocator_difference_type_test.cpp | 6 +- test/allocator_is_always_equal_test.cpp | 1 - test/allocator_pocca_test.cpp | 1 - test/allocator_pocma_test.cpp | 1 - test/allocator_pocs_test.cpp | 1 - test/allocator_pointer_test.cpp | 6 +- test/allocator_rebind_test.cpp | 6 +- test/allocator_size_type_test.cpp | 11 ++- test/allocator_value_type_test.cpp | 4 +- test/allocator_void_pointer_test.cpp | 6 +- test/detail_iterator_test.cpp | 4 +- test/eif_lazy_test.cpp | 12 +-- test/is_same_test.cpp | 26 +++--- test/iterator_test.cpp | 4 +- test/pointer_traits_difference_type_test.cpp | 20 ++--- test/pointer_traits_element_type_test.cpp | 32 +++---- test/pointer_traits_pointer_test.cpp | 14 +-- test/pointer_traits_rebind_test.cpp | 86 +++++++++---------- test/quick.cpp | 3 +- test/ref_ct_test.cpp | 12 +-- test/ref_test.cpp | 2 +- test/sv_types_test.cpp | 1 - test/underlying_type.cpp | 6 +- 34 files changed, 206 insertions(+), 168 deletions(-) create mode 100644 include/boost/core/detail/is_same.hpp diff --git a/doc/changes.qbk b/doc/changes.qbk index e314558..8e63a18 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -11,6 +11,9 @@ * Added [link core.snprintf `boost/core/snprintf.hpp`] header with portable definitions of `snprintf`, `vsnprintf` and their `wchar_t` counterparts. +* Deprecated `boost/core/is_same.hpp` and `boost::core::is_same`. The header will be removed in a future release. + Users are advised to use [@http://www.boost.org/doc/libs/release/libs/type_traits/doc/html/index.html Boost.TypeTraits] + or C++ standard library type traits instead. [endsect] diff --git a/doc/is_same.qbk b/doc/is_same.qbk index 657c591..304ae4e 100644 --- a/doc/is_same.qbk +++ b/doc/is_same.qbk @@ -17,6 +17,11 @@ [section Header ] +[warning This component is deprecated and will be removed in a future release. +Users are recommended to use `boost::is_same` from +[@http://www.boost.org/doc/libs/release/libs/type_traits/doc/html/index.html Boost.TypeTraits] +or `std::is_same` from C++ standard library `` instead.] + The header `` defines the class template `boost::core::is_same`. It defines a nested integral constant `value` which is `true` when `T1` and `T2` are the same type, and diff --git a/doc/lightweight_test.qbk b/doc/lightweight_test.qbk index 698485a..9073b08 100644 --- a/doc/lightweight_test.qbk +++ b/doc/lightweight_test.qbk @@ -326,14 +326,14 @@ parentheses.) `` #include -#include +#include template struct X { typedef T type; }; -using boost::core::is_same; +using boost::is_same; int main() { diff --git a/include/boost/core/detail/is_same.hpp b/include/boost/core/detail/is_same.hpp new file mode 100644 index 0000000..634d300 --- /dev/null +++ b/include/boost/core/detail/is_same.hpp @@ -0,0 +1,39 @@ +#ifndef BOOST_CORE_DETAIL_IS_SAME_HPP_INCLUDED +#define BOOST_CORE_DETAIL_IS_SAME_HPP_INCLUDED + +// is_same::value is true when T1 == T2 +// +// Copyright 2014 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include + +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +namespace boost +{ +namespace core +{ +namespace detail +{ + +template< class T1, class T2 > struct is_same +{ + BOOST_STATIC_CONSTANT( bool, value = false ); +}; + +template< class T > struct is_same< T, T > +{ + BOOST_STATIC_CONSTANT( bool, value = true ); +}; + +} // namespace detail +} // namespace core +} // namespace boost + +#endif // #ifndef BOOST_CORE_DETAIL_IS_SAME_HPP_INCLUDED diff --git a/include/boost/core/detail/string_view.hpp b/include/boost/core/detail/string_view.hpp index 5a1f6c8..1d89b8b 100644 --- a/include/boost/core/detail/string_view.hpp +++ b/include/boost/core/detail/string_view.hpp @@ -14,7 +14,7 @@ // https://www.boost.org/LICENSE_1_0.txt #include -#include +#include #include #include #include @@ -381,7 +381,7 @@ public: } template BOOST_CXX14_CONSTEXPR basic_string_view( Ch const* first, End last, - typename boost::enable_if >::type* = 0 ) BOOST_NOEXCEPT: p_( first ), n_( last - first ) + typename boost::enable_if >::type* = 0 ) BOOST_NOEXCEPT: p_( first ), n_( last - first ) { BOOST_ASSERT( last - first >= 0 ); } @@ -399,7 +399,7 @@ public: #endif template basic_string_view( boost::basic_string_view > const& str, - typename boost::enable_if >::type* = 0 ) BOOST_NOEXCEPT: p_( str.data() ), n_( str.size() ) + typename boost::enable_if >::type* = 0 ) BOOST_NOEXCEPT: p_( str.data() ), n_( str.size() ) { } @@ -430,7 +430,7 @@ public: #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) - template >::type> + template >::type> operator std::basic_string_view() const BOOST_NOEXCEPT { return std::basic_string_view( data(), size() ); @@ -439,7 +439,7 @@ public: #endif template operator boost::basic_string_view, std::char_traits >::type> () const BOOST_NOEXCEPT + typename boost::enable_if, std::char_traits >::type> () const BOOST_NOEXCEPT { return boost::basic_string_view< Ch, std::char_traits >( data(), size() ); } @@ -605,7 +605,7 @@ public: if( cmp != 0 ) return cmp; if( size() == str.size() ) return 0; - + return size() < str.size()? -1: +1; } diff --git a/include/boost/core/is_same.hpp b/include/boost/core/is_same.hpp index f373c65..111cbd1 100644 --- a/include/boost/core/is_same.hpp +++ b/include/boost/core/is_same.hpp @@ -1,12 +1,6 @@ #ifndef BOOST_CORE_IS_SAME_HPP_INCLUDED #define BOOST_CORE_IS_SAME_HPP_INCLUDED -// MS compatible compilers support #pragma once - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - // is_same::value is true when T1 == T2 // // Copyright 2014 Peter Dimov @@ -16,6 +10,15 @@ // http://www.boost.org/LICENSE_1_0.txt #include +#include + +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include + +BOOST_HEADER_DEPRECATED("") namespace boost { @@ -23,15 +26,7 @@ namespace boost namespace core { -template< class T1, class T2 > struct is_same -{ - BOOST_STATIC_CONSTANT( bool, value = false ); -}; - -template< class T > struct is_same< T, T > -{ - BOOST_STATIC_CONSTANT( bool, value = true ); -}; +using boost::core::detail::is_same; } // namespace core diff --git a/include/boost/core/lightweight_test_trait.hpp b/include/boost/core/lightweight_test_trait.hpp index 77a1fcd..eea2371 100644 --- a/include/boost/core/lightweight_test_trait.hpp +++ b/include/boost/core/lightweight_test_trait.hpp @@ -22,7 +22,7 @@ #include #include -#include +#include #include namespace boost @@ -56,7 +56,7 @@ template inline bool test_trait_same_impl_( T ) } template inline void test_trait_same_impl( char const * types, - boost::core::is_same same, char const * file, int line, char const * function ) + boost::core::detail::is_same same, char const * file, int line, char const * function ) { if( test_trait_same_impl_( same ) ) { @@ -86,6 +86,6 @@ template inline void test_trait_same_impl( char const * type # pragma GCC system_header #endif -#define BOOST_TEST_TRAIT_SAME(...) ( ::boost::detail::test_trait_same_impl(#__VA_ARGS__, ::boost::core::is_same<__VA_ARGS__>(), __FILE__, __LINE__, BOOST_CURRENT_FUNCTION) ) +#define BOOST_TEST_TRAIT_SAME(...) ( ::boost::detail::test_trait_same_impl(#__VA_ARGS__, ::boost::core::detail::is_same< __VA_ARGS__ >(), __FILE__, __LINE__, BOOST_CURRENT_FUNCTION) ) #endif // #ifndef BOOST_CORE_LIGHTWEIGHT_TEST_TRAIT_HPP diff --git a/include/boost/core/type_name.hpp b/include/boost/core/type_name.hpp index 21faa3c..81c18e6 100644 --- a/include/boost/core/type_name.hpp +++ b/include/boost/core/type_name.hpp @@ -14,7 +14,6 @@ // https://www.boost.org/LICENSE_1_0.txt #include -#include #include #include #include diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5521551..88c0889 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -6,7 +6,7 @@ include(BoostTestJamfile OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST) if(HAVE_BOOST_TEST) -boost_test_jamfile(FILE Jamfile.v2 LINK_LIBRARIES Boost::core Boost::static_assert) +boost_test_jamfile(FILE Jamfile.v2 LINK_LIBRARIES Boost::core Boost::static_assert Boost::type_traits) set(BOOST_TEST_LINK_LIBRARIES Boost::core Boost::type_traits) diff --git a/test/allocator_const_pointer_test.cpp b/test/allocator_const_pointer_test.cpp index fb83627..ef0dec1 100644 --- a/test/allocator_const_pointer_test.cpp +++ b/test/allocator_const_pointer_test.cpp @@ -6,8 +6,8 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include +#include template struct A1 { @@ -22,9 +22,9 @@ struct A2 { int main() { - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); return boost::report_errors(); } diff --git a/test/allocator_const_void_pointer_test.cpp b/test/allocator_const_void_pointer_test.cpp index 9f8610c..c611d5f 100644 --- a/test/allocator_const_void_pointer_test.cpp +++ b/test/allocator_const_void_pointer_test.cpp @@ -6,8 +6,8 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include +#include template struct A1 { @@ -27,9 +27,9 @@ struct A2 { int main() { - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); return boost::report_errors(); } diff --git a/test/allocator_difference_type_test.cpp b/test/allocator_difference_type_test.cpp index c0c0316..610f592 100644 --- a/test/allocator_difference_type_test.cpp +++ b/test/allocator_difference_type_test.cpp @@ -6,8 +6,8 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include +#include template struct A1 { @@ -22,9 +22,9 @@ struct A2 { int main() { - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); return boost::report_errors(); } diff --git a/test/allocator_is_always_equal_test.cpp b/test/allocator_is_always_equal_test.cpp index fd2c03e..378eb19 100644 --- a/test/allocator_is_always_equal_test.cpp +++ b/test/allocator_is_always_equal_test.cpp @@ -6,7 +6,6 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include template diff --git a/test/allocator_pocca_test.cpp b/test/allocator_pocca_test.cpp index 853473a..40a7aa1 100644 --- a/test/allocator_pocca_test.cpp +++ b/test/allocator_pocca_test.cpp @@ -6,7 +6,6 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include template diff --git a/test/allocator_pocma_test.cpp b/test/allocator_pocma_test.cpp index 6c0c8e3..7738054 100644 --- a/test/allocator_pocma_test.cpp +++ b/test/allocator_pocma_test.cpp @@ -6,7 +6,6 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include template diff --git a/test/allocator_pocs_test.cpp b/test/allocator_pocs_test.cpp index 2f90f3f..bf62738 100644 --- a/test/allocator_pocs_test.cpp +++ b/test/allocator_pocs_test.cpp @@ -6,7 +6,6 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include template diff --git a/test/allocator_pointer_test.cpp b/test/allocator_pointer_test.cpp index 6ff445e..a88fc7e 100644 --- a/test/allocator_pointer_test.cpp +++ b/test/allocator_pointer_test.cpp @@ -6,8 +6,8 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include +#include template struct A1 { @@ -22,9 +22,9 @@ struct A2 { int main() { - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); return boost::report_errors(); } diff --git a/test/allocator_rebind_test.cpp b/test/allocator_rebind_test.cpp index 88015f2..5f1577a 100644 --- a/test/allocator_rebind_test.cpp +++ b/test/allocator_rebind_test.cpp @@ -6,8 +6,8 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include +#include template struct A1 { @@ -25,9 +25,9 @@ struct A2 { int main() { - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::allocator_rebind, bool>::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::allocator_rebind, int>::type>)); return boost::report_errors(); } diff --git a/test/allocator_size_type_test.cpp b/test/allocator_size_type_test.cpp index cb84965..50301ca 100644 --- a/test/allocator_size_type_test.cpp +++ b/test/allocator_size_type_test.cpp @@ -6,8 +6,11 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include +#include +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +#include +#endif template struct A1 { @@ -24,11 +27,11 @@ struct A2 { int main() { - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); #if !defined(BOOST_NO_CXX11_ALLOCATOR) - BOOST_TEST_TRAIT_TRUE((boost::core::is_same< - std::make_unsigned::type, + BOOST_TEST_TRAIT_TRUE((boost::is_same< + boost::make_unsigned::type, boost::allocator_size_type >::type>)); #endif return boost::report_errors(); diff --git a/test/allocator_value_type_test.cpp b/test/allocator_value_type_test.cpp index 575222c..eb9c92a 100644 --- a/test/allocator_value_type_test.cpp +++ b/test/allocator_value_type_test.cpp @@ -6,8 +6,8 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include +#include template struct A { @@ -16,7 +16,7 @@ struct A { int main() { - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); return boost::report_errors(); } diff --git a/test/allocator_void_pointer_test.cpp b/test/allocator_void_pointer_test.cpp index d7133be..1569673 100644 --- a/test/allocator_void_pointer_test.cpp +++ b/test/allocator_void_pointer_test.cpp @@ -6,8 +6,8 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include +#include template struct A1 { @@ -27,9 +27,9 @@ struct A2 { int main() { - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); return boost::report_errors(); } diff --git a/test/detail_iterator_test.cpp b/test/detail_iterator_test.cpp index 13eef58..0865ec4 100644 --- a/test/detail_iterator_test.cpp +++ b/test/detail_iterator_test.cpp @@ -10,8 +10,8 @@ #define BOOST_ALLOW_DEPRECATED_HEADERS #include -#include #include +#include #include #include @@ -62,7 +62,7 @@ struct iterator int main() { - using boost::core::is_same; + using boost::is_same; /* template struct iterator_traits { diff --git a/test/eif_lazy_test.cpp b/test/eif_lazy_test.cpp index 8938a3d..3eb1ae7 100644 --- a/test/eif_lazy_test.cpp +++ b/test/eif_lazy_test.cpp @@ -12,7 +12,7 @@ // Testing all variations of lazy_enable_if. -#include +#include #include #include @@ -26,7 +26,7 @@ using boost::lazy_disable_if_c; template struct is_int_or_double { BOOST_STATIC_CONSTANT(bool, - value = (boost::is_same::value || + value = (boost::is_same::value || boost::is_same::value)); }; @@ -84,14 +84,14 @@ int main() BOOST_TEST(foo(1)); BOOST_TEST(foo(1.0)); - BOOST_TEST(!foo("1")); - BOOST_TEST(!foo(static_cast(0))); + BOOST_TEST(!foo("1")); + BOOST_TEST(!foo(static_cast(0))); BOOST_TEST(foo2(1)); BOOST_TEST(foo2(1.0)); - BOOST_TEST(!foo2("1")); - BOOST_TEST(!foo2(static_cast(0))); + BOOST_TEST(!foo2("1")); + BOOST_TEST(!foo2(static_cast(0))); return boost::report_errors(); } diff --git a/test/is_same_test.cpp b/test/is_same_test.cpp index 838db22..23a927c 100644 --- a/test/is_same_test.cpp +++ b/test/is_same_test.cpp @@ -1,5 +1,5 @@ // -// Test for core::is_same +// Test for core::detail::is_same // // Copyright 2014 Peter Dimov // @@ -8,7 +8,7 @@ // http://www.boost.org/LICENSE_1_0.txt // -#include +#include #include struct X @@ -21,18 +21,18 @@ struct Y int main() { - BOOST_TEST_TRAIT_TRUE(( boost::core::is_same )); - BOOST_TEST_TRAIT_TRUE(( boost::core::is_same )); - BOOST_TEST_TRAIT_TRUE(( boost::core::is_same )); - BOOST_TEST_TRAIT_TRUE(( boost::core::is_same )); - BOOST_TEST_TRAIT_TRUE(( boost::core::is_same )); + BOOST_TEST_TRAIT_TRUE(( boost::core::detail::is_same )); + BOOST_TEST_TRAIT_TRUE(( boost::core::detail::is_same )); + BOOST_TEST_TRAIT_TRUE(( boost::core::detail::is_same )); + BOOST_TEST_TRAIT_TRUE(( boost::core::detail::is_same )); + BOOST_TEST_TRAIT_TRUE(( boost::core::detail::is_same )); - BOOST_TEST_TRAIT_FALSE(( boost::core::is_same )); - BOOST_TEST_TRAIT_FALSE(( boost::core::is_same )); - BOOST_TEST_TRAIT_FALSE(( boost::core::is_same )); - BOOST_TEST_TRAIT_FALSE(( boost::core::is_same )); - BOOST_TEST_TRAIT_FALSE(( boost::core::is_same )); - BOOST_TEST_TRAIT_FALSE(( boost::core::is_same )); + BOOST_TEST_TRAIT_FALSE(( boost::core::detail::is_same )); + BOOST_TEST_TRAIT_FALSE(( boost::core::detail::is_same )); + BOOST_TEST_TRAIT_FALSE(( boost::core::detail::is_same )); + BOOST_TEST_TRAIT_FALSE(( boost::core::detail::is_same )); + BOOST_TEST_TRAIT_FALSE(( boost::core::detail::is_same )); + BOOST_TEST_TRAIT_FALSE(( boost::core::detail::is_same )); return boost::report_errors(); } diff --git a/test/iterator_test.cpp b/test/iterator_test.cpp index 3cbf038..5d8c52a 100644 --- a/test/iterator_test.cpp +++ b/test/iterator_test.cpp @@ -18,8 +18,8 @@ #if BOOST_CXX_VERSION < 201703 #include -#include #include +#include /* @@ -60,7 +60,7 @@ struct R int main() { - using boost::core::is_same; + using boost::is_same; BOOST_TEST_TRAIT_TRUE((is_same::iterator_category,C>)); BOOST_TEST_TRAIT_TRUE((is_same::value_type,T>)); diff --git a/test/pointer_traits_difference_type_test.cpp b/test/pointer_traits_difference_type_test.cpp index e9d0b09..52ad709 100644 --- a/test/pointer_traits_difference_type_test.cpp +++ b/test/pointer_traits_difference_type_test.cpp @@ -6,8 +6,8 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include +#include template struct P { }; @@ -19,23 +19,23 @@ struct E { int main() { - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::difference_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::difference_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::difference_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::difference_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::difference_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::difference_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::difference_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::difference_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::difference_type>)); return boost::report_errors(); } diff --git a/test/pointer_traits_element_type_test.cpp b/test/pointer_traits_element_type_test.cpp index a20733e..2b1bf12 100644 --- a/test/pointer_traits_element_type_test.cpp +++ b/test/pointer_traits_element_type_test.cpp @@ -6,8 +6,8 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include +#include template struct P1 { }; @@ -45,39 +45,39 @@ struct E { int main() { - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::element_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); #endif - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); #endif - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::element_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::element_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); return boost::report_errors(); } diff --git a/test/pointer_traits_pointer_test.cpp b/test/pointer_traits_pointer_test.cpp index a98eb4d..c8070f2 100644 --- a/test/pointer_traits_pointer_test.cpp +++ b/test/pointer_traits_pointer_test.cpp @@ -6,25 +6,25 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include +#include template struct P { }; int main() { - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::pointer>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::pointer>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::pointer>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::pointer>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::pointer>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::pointer>)); return boost::report_errors(); } diff --git a/test/pointer_traits_rebind_test.cpp b/test/pointer_traits_rebind_test.cpp index a009463..42c510e 100644 --- a/test/pointer_traits_rebind_test.cpp +++ b/test/pointer_traits_rebind_test.cpp @@ -6,8 +6,8 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include +#include template struct P1 { }; @@ -55,94 +55,94 @@ struct R { }; int main() { - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); #endif - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::rebind >)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind >)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind >)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind >)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::rebind >)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind >)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::rebind >)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind >)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::rebind >)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind >)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::rebind >)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind >)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind >)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind >)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind >)); #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind >)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind >)); #endif - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind >)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind >)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind >)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind >)); #endif return boost::report_errors(); diff --git a/test/quick.cpp b/test/quick.cpp index fdfe983..4b381db 100644 --- a/test/quick.cpp +++ b/test/quick.cpp @@ -16,13 +16,12 @@ #include #include #include -#include #include #include #include #include #include -#include +#include #include #include #include diff --git a/test/ref_ct_test.cpp b/test/ref_ct_test.cpp index 9e5bf31..d69d013 100644 --- a/test/ref_ct_test.cpp +++ b/test/ref_ct_test.cpp @@ -6,10 +6,10 @@ // compile-time test for "boost/ref.hpp" header content // see 'ref_test.cpp' for run-time part -#include -#include +#include #include #include +#include namespace { @@ -17,8 +17,8 @@ template< typename T, typename U > void ref_test(boost::reference_wrapper) { typedef typename boost::reference_wrapper::type type; - BOOST_STATIC_ASSERT((boost::core::is_same::value)); - BOOST_STATIC_ASSERT((boost::core::is_same::value)); + BOOST_STATIC_ASSERT((boost::is_same::value)); + BOOST_STATIC_ASSERT((boost::is_same::value)); } template< typename T > @@ -42,14 +42,14 @@ void is_reference_wrapper_test(T) template< typename R, typename Ref > void cxx_reference_test(Ref) { - BOOST_STATIC_ASSERT((boost::core::is_same::value)); + BOOST_STATIC_ASSERT((boost::is_same::value)); } template< typename R, typename Ref > void unwrap_reference_test(Ref) { typedef typename boost::unwrap_reference::type type; - BOOST_STATIC_ASSERT((boost::core::is_same::value)); + BOOST_STATIC_ASSERT((boost::is_same::value)); } } // namespace diff --git a/test/ref_test.cpp b/test/ref_test.cpp index 6251b74..78585ad 100644 --- a/test/ref_test.cpp +++ b/test/ref_test.cpp @@ -6,7 +6,7 @@ // run-time test for "boost/ref.hpp" header content // see 'ref_ct_test.cpp' for compile-time part -#include +#include #include namespace { diff --git a/test/sv_types_test.cpp b/test/sv_types_test.cpp index 9011f0c..9afe05b 100644 --- a/test/sv_types_test.cpp +++ b/test/sv_types_test.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include struct Ch diff --git a/test/underlying_type.cpp b/test/underlying_type.cpp index 34f3940..27bc4f9 100644 --- a/test/underlying_type.cpp +++ b/test/underlying_type.cpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #if defined(_MSC_VER) @@ -63,9 +63,9 @@ struct underlying_type< native_enum > int main(int, char*[]) { - BOOST_TEST_TRAIT_TRUE((boost::core::is_same< boost::underlying_type< emulated_enum >::type, unsigned char >)); + BOOST_TEST_TRAIT_TRUE((boost::is_same< boost::underlying_type< emulated_enum >::type, unsigned char >)); #if !defined(BOOST_NO_CXX11_SCOPED_ENUMS) - BOOST_TEST_TRAIT_TRUE((boost::core::is_same< boost::underlying_type< native_enum >::type, unsigned short >)); + BOOST_TEST_TRAIT_TRUE((boost::is_same< boost::underlying_type< native_enum >::type, unsigned short >)); #endif return boost::report_errors(); From ddc6cc25a9a0f742e1042c55c9d908e678e152bf Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Thu, 22 Dec 2022 18:59:27 +0300 Subject: [PATCH 248/258] Actualized includes of ref.hpp. --- test/ref_conversion_test.cpp | 2 +- test/ref_ct_test.cpp | 2 +- test/ref_cv_test.cpp | 2 +- test/ref_fn_test.cpp | 2 +- test/ref_implicit_fail.cpp | 2 +- test/ref_implicit_fail2.cpp | 2 +- test/ref_implicit_fail3.cpp | 2 +- test/ref_implicit_fail4.cpp | 2 +- test/ref_ref_test.cpp | 2 +- test/ref_rv_fail1.cpp | 2 +- test/ref_rv_fail2.cpp | 2 +- test/ref_rv_fail3.cpp | 2 +- test/ref_rv_fail4.cpp | 2 +- test/ref_rv_fail5.cpp | 2 +- test/ref_test.cpp | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/test/ref_conversion_test.cpp b/test/ref_conversion_test.cpp index 6c336ca..2eed2ba 100644 --- a/test/ref_conversion_test.cpp +++ b/test/ref_conversion_test.cpp @@ -6,7 +6,7 @@ // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt -#include +#include #include struct X diff --git a/test/ref_ct_test.cpp b/test/ref_ct_test.cpp index d69d013..624e007 100644 --- a/test/ref_ct_test.cpp +++ b/test/ref_ct_test.cpp @@ -3,7 +3,7 @@ // 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -// compile-time test for "boost/ref.hpp" header content +// compile-time test for "boost/core/ref.hpp" header content // see 'ref_test.cpp' for run-time part #include diff --git a/test/ref_cv_test.cpp b/test/ref_cv_test.cpp index 734d9b3..bfba505 100644 --- a/test/ref_cv_test.cpp +++ b/test/ref_cv_test.cpp @@ -6,7 +6,7 @@ // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt -#include +#include #include #define BOOST_TEST_REF( x ) BOOST_TEST( &boost::ref( x ).get() == &x ) diff --git a/test/ref_fn_test.cpp b/test/ref_fn_test.cpp index be13824..83fdbd8 100644 --- a/test/ref_fn_test.cpp +++ b/test/ref_fn_test.cpp @@ -15,7 +15,7 @@ // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt -#include +#include #include diff --git a/test/ref_implicit_fail.cpp b/test/ref_implicit_fail.cpp index a012f52..4f384f6 100644 --- a/test/ref_implicit_fail.cpp +++ b/test/ref_implicit_fail.cpp @@ -8,7 +8,7 @@ // http://www.boost.org/LICENSE_1_0.txt // -#include +#include void f( boost::reference_wrapper< int > ) { diff --git a/test/ref_implicit_fail2.cpp b/test/ref_implicit_fail2.cpp index ff67630..e33c6fc 100644 --- a/test/ref_implicit_fail2.cpp +++ b/test/ref_implicit_fail2.cpp @@ -8,7 +8,7 @@ // http://www.boost.org/LICENSE_1_0.txt // -#include +#include void f( boost::reference_wrapper< int const > ) { diff --git a/test/ref_implicit_fail3.cpp b/test/ref_implicit_fail3.cpp index 726feb4..5a45976 100644 --- a/test/ref_implicit_fail3.cpp +++ b/test/ref_implicit_fail3.cpp @@ -8,7 +8,7 @@ // http://www.boost.org/LICENSE_1_0.txt // -#include +#include struct X { diff --git a/test/ref_implicit_fail4.cpp b/test/ref_implicit_fail4.cpp index 5f5e0c9..6fda3ce 100644 --- a/test/ref_implicit_fail4.cpp +++ b/test/ref_implicit_fail4.cpp @@ -8,7 +8,7 @@ // http://www.boost.org/LICENSE_1_0.txt // -#include +#include void f( boost::reference_wrapper< int const > ) { diff --git a/test/ref_ref_test.cpp b/test/ref_ref_test.cpp index 46be561..064b3d2 100644 --- a/test/ref_ref_test.cpp +++ b/test/ref_ref_test.cpp @@ -11,7 +11,7 @@ // http://www.boost.org/LICENSE_1_0.txt // -#include +#include #include template void test( T const & t ) diff --git a/test/ref_rv_fail1.cpp b/test/ref_rv_fail1.cpp index 1c0a2e6..95bba18 100644 --- a/test/ref_rv_fail1.cpp +++ b/test/ref_rv_fail1.cpp @@ -8,7 +8,7 @@ // http://www.boost.org/LICENSE_1_0.txt // -#include +#include #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) diff --git a/test/ref_rv_fail2.cpp b/test/ref_rv_fail2.cpp index 8ce2680..20657bf 100644 --- a/test/ref_rv_fail2.cpp +++ b/test/ref_rv_fail2.cpp @@ -8,7 +8,7 @@ // http://www.boost.org/LICENSE_1_0.txt // -#include +#include int main() { diff --git a/test/ref_rv_fail3.cpp b/test/ref_rv_fail3.cpp index 14b39b8..dd3b5b6 100644 --- a/test/ref_rv_fail3.cpp +++ b/test/ref_rv_fail3.cpp @@ -8,7 +8,7 @@ // http://www.boost.org/LICENSE_1_0.txt // -#include +#include #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) diff --git a/test/ref_rv_fail4.cpp b/test/ref_rv_fail4.cpp index 899de7b..9a8bc50 100644 --- a/test/ref_rv_fail4.cpp +++ b/test/ref_rv_fail4.cpp @@ -9,7 +9,7 @@ // http://www.boost.org/LICENSE_1_0.txt // -#include +#include #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) diff --git a/test/ref_rv_fail5.cpp b/test/ref_rv_fail5.cpp index ed18edf..5ddbc5f 100644 --- a/test/ref_rv_fail5.cpp +++ b/test/ref_rv_fail5.cpp @@ -9,7 +9,7 @@ // http://www.boost.org/LICENSE_1_0.txt // -#include +#include #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) diff --git a/test/ref_test.cpp b/test/ref_test.cpp index 78585ad..2efbcde 100644 --- a/test/ref_test.cpp +++ b/test/ref_test.cpp @@ -3,7 +3,7 @@ // 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -// run-time test for "boost/ref.hpp" header content +// run-time test for "boost/core/ref.hpp" header content // see 'ref_ct_test.cpp' for compile-time part #include From 843e0f7bb0d1ad5c53f4ccbe8075afd5b2c3562a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 28 Dec 2022 17:49:01 +0200 Subject: [PATCH 249/258] Add boost::core::detail::lwt_unattended() --- include/boost/core/detail/lwt_unattended.hpp | 45 ++++++++++++++++++++ include/boost/core/lightweight_test.hpp | 37 +++++++--------- 2 files changed, 61 insertions(+), 21 deletions(-) create mode 100644 include/boost/core/detail/lwt_unattended.hpp diff --git a/include/boost/core/detail/lwt_unattended.hpp b/include/boost/core/detail/lwt_unattended.hpp new file mode 100644 index 0000000..68cba62 --- /dev/null +++ b/include/boost/core/detail/lwt_unattended.hpp @@ -0,0 +1,45 @@ +#ifndef BOOST_CORE_DETAIL_LWT_UNATTENDED_HPP_INCLUDED +#define BOOST_CORE_DETAIL_LWT_UNATTENDED_HPP_INCLUDED + +// Copyright 2014, 2022 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#if defined(_MSC_VER) && defined(_CPPLIB_VER) && defined(_DEBUG) +# include +#endif + +namespace boost +{ +namespace core +{ +namespace detail +{ + +// Setup unattended mode by disabling interactive popups on +// assertion failures + +inline void lwt_unattended() +{ +#if defined(_MSC_VER) && (_MSC_VER > 1310) + + // disable message boxes on assert(), abort() + ::_set_abort_behavior( 0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT ); + +#endif + +#if defined(_MSC_VER) && defined(_CPPLIB_VER) && defined(_DEBUG) + + // disable message boxes on iterator debugging violations + _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR ); + +#endif +} + +} // namespace detail +} // namespace core +} // namespace boost + +#endif // #ifndef BOOST_CORE_DETAIL_LWT_UNATTENDED_HPP_INCLUDED diff --git a/include/boost/core/lightweight_test.hpp b/include/boost/core/lightweight_test.hpp index 37d713d..83f20bc 100644 --- a/include/boost/core/lightweight_test.hpp +++ b/include/boost/core/lightweight_test.hpp @@ -22,6 +22,7 @@ // http://www.boost.org/LICENSE_1_0.txt // +#include #include #include #include @@ -33,10 +34,6 @@ #include #include -#if defined(_MSC_VER) && defined(_CPPLIB_VER) && defined(_DEBUG) -# include -#endif - // IDE's like Visual Studio perform better if output goes to std::cout or // some other stream, so allow user to configure output stream: #ifndef BOOST_LIGHTWEIGHT_TEST_OSTREAM @@ -49,38 +46,36 @@ namespace boost namespace detail { -class test_result { +class test_result +{ public: - test_result() - : report_(false) - , errors_(0) { -#if defined(_MSC_VER) && (_MSC_VER > 1310) - // disable message boxes on assert(), abort() - ::_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); -#endif -#if defined(_MSC_VER) && defined(_CPPLIB_VER) && defined(_DEBUG) - // disable message boxes on iterator debugging violations - _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE ); - _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR ); -#endif + + test_result(): report_( false ), errors_( 0 ) + { + core::detail::lwt_unattended(); } - ~test_result() { - if (!report_) { + ~test_result() + { + if( !report_ ) + { BOOST_LIGHTWEIGHT_TEST_OSTREAM << "main() should return report_errors()" << std::endl; std::abort(); } } - int& errors() { + int& errors() + { return errors_; } - void done() { + void done() + { report_ = true; } private: + bool report_; int errors_; }; From 6299da9273f3768f0bad59d53da5b057875dcbcd Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 30 Dec 2022 21:17:58 +0200 Subject: [PATCH 250/258] Add boost::core::lwt_init() --- include/boost/core/lightweight_test.hpp | 10 +++++++++- test/Jamfile.v2 | 1 + test/lightweight_test_fail16.cpp | 12 ++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 test/lightweight_test_fail16.cpp diff --git a/include/boost/core/lightweight_test.hpp b/include/boost/core/lightweight_test.hpp index 83f20bc..c09ce87 100644 --- a/include/boost/core/lightweight_test.hpp +++ b/include/boost/core/lightweight_test.hpp @@ -42,7 +42,6 @@ namespace boost { - namespace detail { @@ -519,6 +518,15 @@ inline int report_errors() return errors < 256? errors: 255; } +namespace core +{ + +inline void lwt_init() +{ + boost::detail::test_results(); +} + +} // namespace core } // namespace boost #define BOOST_TEST(expr) ( ::boost::detail::test_impl(#expr, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, (expr)? true: false) ) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index bf44f47..ffe7b4d 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -148,6 +148,7 @@ run-fail lightweight_test_fail12.cpp ; run-fail lightweight_test_fail13.cpp ; run-fail lightweight_test_fail14.cpp ; run-fail lightweight_test_fail15.cpp ; +run-fail lightweight_test_fail16.cpp ; run-fail lightweight_test_lt_fail.cpp ; run-fail lightweight_test_le_fail.cpp ; run-fail lightweight_test_gt_fail.cpp ; diff --git a/test/lightweight_test_fail16.cpp b/test/lightweight_test_fail16.cpp new file mode 100644 index 0000000..dbeb3c0 --- /dev/null +++ b/test/lightweight_test_fail16.cpp @@ -0,0 +1,12 @@ +// Copyright 2022 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include + +// Should fail, because boost::report_errors() hasn't been called + +int main() +{ + boost::core::lwt_init(); +} From 2d302c1666d4b791e942825290ba89c80c9f3fe4 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 30 Dec 2022 21:57:12 +0200 Subject: [PATCH 251/258] Document boost::core::lwt_init --- doc/lightweight_test.qbk | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/doc/lightweight_test.qbk b/doc/lightweight_test.qbk index 9073b08..8c7fa4d 100644 --- a/doc/lightweight_test.qbk +++ b/doc/lightweight_test.qbk @@ -51,8 +51,16 @@ When using `lightweight_test.hpp`, *do not forget* to namespace boost { - int report_errors(); -} + +int report_errors(); + +namespace core +{ + +void lwt_init(); + +} // namespace core +} // namespace boost `` [endsect] @@ -246,6 +254,25 @@ Return the error count from `main`. [endsect] +[section lwt_init] + +`` +void boost::core::lwt_init() +`` + +Performs one-time initialization. Disables the interactive message +boxes displayed by the Microsoft Windows debug runtime library on +`abort`, failing `assert`, and other abnormal program terminations +(to facilitate unattended testing), and ensures that in case +`boost::report_errors` is not called (a common mistake), the program +ends with a nonzero exit code. + +`lwt_init` is automatically called by the test macros. There is +no need to call it explicitly, except in cases where a test fails due +to e.g. an assertion failure before the first test macro is invoked. + +[endsect] + [section Example] `` From 8caca51c4d16d1b3dc7688c132b075b4d782c89a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 30 Dec 2022 22:03:06 +0200 Subject: [PATCH 252/258] Do not run lightweight_test_fail16.cpp under CMake, as CTest doesn't like std::abort --- test/Jamfile.v2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index ffe7b4d..e9743be 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -148,7 +148,7 @@ run-fail lightweight_test_fail12.cpp ; run-fail lightweight_test_fail13.cpp ; run-fail lightweight_test_fail14.cpp ; run-fail lightweight_test_fail15.cpp ; -run-fail lightweight_test_fail16.cpp ; +run-fail lightweight_test_fail16.cpp : ; run-fail lightweight_test_lt_fail.cpp ; run-fail lightweight_test_le_fail.cpp ; run-fail lightweight_test_gt_fail.cpp ; From 1825265014f6c752a8f078ad51de4d36bcc02b27 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Fri, 6 Jan 2023 19:12:47 +0300 Subject: [PATCH 253/258] Marked boost::ref methods and associated functions with noexcept. --- doc/changes.qbk | 1 + include/boost/core/ref.hpp | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/doc/changes.qbk b/doc/changes.qbk index 8e63a18..02a5352 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -14,6 +14,7 @@ * Deprecated `boost/core/is_same.hpp` and `boost::core::is_same`. The header will be removed in a future release. Users are advised to use [@http://www.boost.org/doc/libs/release/libs/type_traits/doc/html/index.html Boost.TypeTraits] or C++ standard library type traits instead. +* Marked `boost::ref` member functions and associated methods with `noexcept`. [endsect] diff --git a/include/boost/core/ref.hpp b/include/boost/core/ref.hpp index a416cbd..6c7a8d0 100644 --- a/include/boost/core/ref.hpp +++ b/include/boost/core/ref.hpp @@ -92,11 +92,11 @@ public: @remark Does not throw. */ - BOOST_FORCEINLINE explicit reference_wrapper(T& t): t_(boost::addressof(t)) {} + BOOST_FORCEINLINE explicit reference_wrapper(T& t) BOOST_NOEXCEPT : t_(boost::addressof(t)) {} #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, == 1600 ) - BOOST_FORCEINLINE explicit reference_wrapper( T & t, ref_workaround_tag ): t_( boost::addressof( t ) ) {} + BOOST_FORCEINLINE explicit reference_wrapper( T & t, ref_workaround_tag ) BOOST_NOEXCEPT : t_( boost::addressof( t ) ) {} #endif @@ -119,7 +119,7 @@ public: */ template reference_wrapper( reference_wrapper r, typename enable_if_c::value, - boost::detail::ref_empty>::type = boost::detail::ref_empty() ): t_( r.t_ ) + boost::detail::ref_empty>::type = boost::detail::ref_empty() ) BOOST_NOEXCEPT : t_( r.t_ ) { } @@ -127,20 +127,20 @@ public: @return The stored reference. @remark Does not throw. */ - BOOST_FORCEINLINE operator T& () const { return *t_; } + BOOST_FORCEINLINE operator T& () const BOOST_NOEXCEPT { return *t_; } /** @return The stored reference. @remark Does not throw. */ - BOOST_FORCEINLINE T& get() const { return *t_; } + BOOST_FORCEINLINE T& get() const BOOST_NOEXCEPT { return *t_; } /** @return A pointer to the object referenced by the stored reference. @remark Does not throw. */ - BOOST_FORCEINLINE T* get_pointer() const { return t_; } + BOOST_FORCEINLINE T* get_pointer() const BOOST_NOEXCEPT { return t_; } private: @@ -165,7 +165,7 @@ private: @return `reference_wrapper(t)` @remark Does not throw. */ -template BOOST_FORCEINLINE reference_wrapper BOOST_REF_CONST ref( T & t ) +template BOOST_FORCEINLINE reference_wrapper BOOST_REF_CONST ref( T & t ) BOOST_NOEXCEPT { #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, == 1600 ) @@ -184,7 +184,7 @@ template BOOST_FORCEINLINE reference_wrapper BOOST_REF_CONST ref( T @return `reference_wrapper(t)` @remark Does not throw. */ -template BOOST_FORCEINLINE reference_wrapper BOOST_REF_CONST cref( T const & t ) +template BOOST_FORCEINLINE reference_wrapper BOOST_REF_CONST cref( T const & t ) BOOST_NOEXCEPT { return reference_wrapper(t); } @@ -315,7 +315,7 @@ template struct unwrap_reference< reference_wrapper const volatil @return `unwrap_reference::type&(t)` @remark Does not throw. */ -template BOOST_FORCEINLINE typename unwrap_reference::type& unwrap_ref( T & t ) +template BOOST_FORCEINLINE typename unwrap_reference::type& unwrap_ref( T & t ) BOOST_NOEXCEPT { return t; } @@ -325,7 +325,7 @@ template BOOST_FORCEINLINE typename unwrap_reference::type& unwrap_r /** @cond */ -template BOOST_FORCEINLINE T* get_pointer( reference_wrapper const & r ) +template BOOST_FORCEINLINE T* get_pointer( reference_wrapper const & r ) BOOST_NOEXCEPT { return r.get_pointer(); } From 1e84baeea31fe2a6b8b5c1fd841207223c18c242 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Fri, 6 Jan 2023 19:38:55 +0300 Subject: [PATCH 254/258] Use defaulted template arguments to restrict boost::ref converting ctor. --- include/boost/core/ref.hpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/include/boost/core/ref.hpp b/include/boost/core/ref.hpp index 6c7a8d0..46db5fe 100644 --- a/include/boost/core/ref.hpp +++ b/include/boost/core/ref.hpp @@ -1,17 +1,15 @@ #ifndef BOOST_CORE_REF_HPP #define BOOST_CORE_REF_HPP -// MS compatible compilers support #pragma once - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - #include #include #include #include +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + // // ref.hpp - ref/cref, useful helper functions // @@ -61,9 +59,11 @@ template< class Y, class T > struct ref_convertible enum _vt { value = sizeof( (f)( static_cast(0) ) ) == sizeof(yes) }; }; +#if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) struct ref_empty { }; +#endif } // namespace detail @@ -117,11 +117,18 @@ public: @remark Only enabled when `Y*` is convertible to `T*`. @remark Does not throw. */ +#if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) + template::value>::type> + reference_wrapper( reference_wrapper r ) BOOST_NOEXCEPT : t_( r.t_ ) + { + } +#else template reference_wrapper( reference_wrapper r, typename enable_if_c::value, boost::detail::ref_empty>::type = boost::detail::ref_empty() ) BOOST_NOEXCEPT : t_( r.t_ ) { } +#endif /** @return The stored reference. From 99f9654f18a7ae2820d65972c01501515e864d33 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 7 Jan 2023 01:06:41 +0300 Subject: [PATCH 255/258] Fixed incorrect preprocessor condition for ref_empty definition. Closes https://github.com/boostorg/core/pull/137. --- include/boost/core/ref.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/core/ref.hpp b/include/boost/core/ref.hpp index 46db5fe..d29a4d6 100644 --- a/include/boost/core/ref.hpp +++ b/include/boost/core/ref.hpp @@ -59,7 +59,7 @@ template< class Y, class T > struct ref_convertible enum _vt { value = sizeof( (f)( static_cast(0) ) ) == sizeof(yes) }; }; -#if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) +#if defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) struct ref_empty { }; From 8a8738a981e1d46146939f93ac0d751b827e7704 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 7 Jan 2023 01:52:02 +0300 Subject: [PATCH 256/258] Propagate noexcept specification in boost::swap. Mark boost::swap noexcept if the type supports non-throwing swap implementation. --- doc/changes.qbk | 1 + doc/swap.qbk | 40 +++++++++++++++++++---------------- include/boost/core/swap.hpp | 29 ++++++++++++++++++------- test/swap/Jamfile.v2 | 1 + test/swap/swap_noexcept.cpp | 42 +++++++++++++++++++++++++++++++++++++ 5 files changed, 88 insertions(+), 25 deletions(-) create mode 100644 test/swap/swap_noexcept.cpp diff --git a/doc/changes.qbk b/doc/changes.qbk index 02a5352..1069b78 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -15,6 +15,7 @@ Users are advised to use [@http://www.boost.org/doc/libs/release/libs/type_traits/doc/html/index.html Boost.TypeTraits] or C++ standard library type traits instead. * Marked `boost::ref` member functions and associated methods with `noexcept`. +* Marked `boost::swap` function with `noexcept`, depending on whether the type supports a non-throwing swap operation. [endsect] diff --git a/doc/swap.qbk b/doc/swap.qbk index dc866fd..5770b9d 100644 --- a/doc/swap.qbk +++ b/doc/swap.qbk @@ -22,7 +22,7 @@ [section Header ] -`template void swap(T& left, T& right);` +[^template void swap(T& left, T& right) noexcept(['see below]);] [endsect] @@ -40,13 +40,14 @@ specialized swap function is available, `std::swap` is used. The generic `std::swap` function requires that the elements to be swapped are assignable and copy constructible. It is usually implemented using one copy construction and two -assignments - this is often both unnecessarily restrictive and -unnecessarily slow. In addition, where the generic swap -implementation provides only the basic guarantee, specialized -swap functions are often able to provide the no-throw exception -guarantee (and it is considered best practice to do so where -possible [footnote Scott Meyers, Effective C++ Third Edition, -Item 25: "Consider support for a non-throwing swap"]. +assignments (C++11 replaces copy operations with move) - this +is often both unnecessarily restrictive and unnecessarily slow. +In addition, where the generic swap implementation provides +only the basic guarantee, specialized swap functions are often +able to provide the no-throw exception guarantee (and it is +considered best practice to do so where possible[footnote Scott +Meyers, Effective C++ Third Edition, Item 25: "Consider support +for a non-throwing swap"]. The alternative to using argument dependent lookup in this situation is to provide a template specialization of @@ -59,12 +60,12 @@ in their own namespaces. `std::swap` originally did not do so, but a request to add an overload of `std::swap` for built-in arrays has been accepted by the C++ Standards Committee[footnote - [@http://open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#809 + [@http://open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#809 LWG Defect Report 809: std::swap should be overloaded for array types]]. [endsect] - + [section Exception Safety] `boost::swap` provides the same exception guarantee as the @@ -73,30 +74,33 @@ of type `T[n]`, where `n > 1` and the underlying swap function for `T` provides the strong exception guarantee, `boost::swap` provides only the basic exception guarantee. +In C++11 and later, `boost::swap` propagates the same `noexcept` +specification as the one specified in the underlying swap function. + [endsect] [section Requirements] Either: -* T must be assignable -* T must be copy constructible +* `T` must be copy assignable (/since C++11:/ move assignable) +* `T` must be copy constructible (/since C++11:/ move constructible) Or: -* A function with the signature `swap(T&,T&)` is available via +* A function with the signature `swap(T&, T&)` is available via argument dependent lookup Or: -* A template specialization of `std::swap` exists for T +* A template specialization of `std::swap` exists for `T` Or: -* T is a built-in array of swappable elements +* `T` is a built-in array of swappable elements [endsect] - + [section Portability] Several older compilers do not support argument dependent @@ -104,11 +108,11 @@ lookup. On these compilers `boost::swap` will call `std::swap`, ignoring any specialized swap functions that could be found as a result of argument dependent lookup. -[endsect] +[endsect] [section Credits] -* *Niels Dekker* - for implementing and documenting support for +* *Niels Dekker* - for implementing and documenting support for built-in arrays * *Joseph Gauterin* - for the initial idea, implementation, tests, and documentation diff --git a/include/boost/core/swap.hpp b/include/boost/core/swap.hpp index 49e1b2d..9952779 100644 --- a/include/boost/core/swap.hpp +++ b/include/boost/core/swap.hpp @@ -13,10 +13,10 @@ // - swap_impl is put outside the boost namespace, to avoid infinite // recursion (causing stack overflow) when swapping objects of a primitive // type. -// - swap_impl has a using-directive, rather than a using-declaration, -// because some compilers (including MSVC 7.1, Borland 5.9.3, and -// Intel 8.1) don't do argument-dependent lookup when it has a -// using-declaration instead. +// - std::swap is imported with a using-directive, rather than +// a using-declaration, because some compilers (including MSVC 7.1, +// Borland 5.9.3, and Intel 8.1) don't do argument-dependent lookup +// when it has a using-declaration instead. // - boost::swap has two template arguments, instead of one, to // avoid ambiguity when swapping objects of a Boost type that does // not have its own boost::swap overload. @@ -30,6 +30,13 @@ #endif #include // for std::size_t +#if defined(BOOST_GCC) && (BOOST_GCC < 40700) +// gcc 4.6 ICEs on noexcept specifications below +#define BOOST_CORE_SWAP_NOEXCEPT_IF(x) +#else +#define BOOST_CORE_SWAP_NOEXCEPT_IF(x) BOOST_NOEXCEPT_IF(x) +#endif + namespace boost_swap_impl { // we can't use type_traits here @@ -37,17 +44,22 @@ namespace boost_swap_impl template struct is_const { enum _vt { value = 0 }; }; template struct is_const { enum _vt { value = 1 }; }; + // Use std::swap if argument dependent lookup fails. + // We need to have this at namespace scope to be able to use unqualified swap() call + // in noexcept specification. + using namespace std; + template BOOST_GPU_ENABLED - void swap_impl(T& left, T& right) + void swap_impl(T& left, T& right) BOOST_CORE_SWAP_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(swap(left, right))) { - using namespace std;//use std::swap if argument dependent lookup fails - swap(left,right); + swap(left, right); } template BOOST_GPU_ENABLED void swap_impl(T (& left)[N], T (& right)[N]) + BOOST_CORE_SWAP_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(::boost_swap_impl::swap_impl(left[0], right[0]))) { for (std::size_t i = 0; i < N; ++i) { @@ -62,9 +74,12 @@ namespace boost BOOST_GPU_ENABLED typename enable_if_c< !boost_swap_impl::is_const::value && !boost_swap_impl::is_const::value >::type swap(T1& left, T2& right) + BOOST_CORE_SWAP_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(::boost_swap_impl::swap_impl(left, right))) { ::boost_swap_impl::swap_impl(left, right); } } +#undef BOOST_CORE_SWAP_NOEXCEPT_IF + #endif diff --git a/test/swap/Jamfile.v2 b/test/swap/Jamfile.v2 index 2b43737..d7f705e 100644 --- a/test/swap/Jamfile.v2 +++ b/test/swap/Jamfile.v2 @@ -13,6 +13,7 @@ compile swap_lib_header_1.cpp ; compile swap_lib_header_2.cpp ; compile swap_mixed_headers_1.cpp ; compile swap_mixed_headers_2.cpp ; +compile swap_noexcept.cpp ; compile-fail swap_const_wrapper_fail.cpp ; diff --git a/test/swap/swap_noexcept.cpp b/test/swap/swap_noexcept.cpp new file mode 100644 index 0000000..cafbde1 --- /dev/null +++ b/test/swap/swap_noexcept.cpp @@ -0,0 +1,42 @@ +// Copyright (c) 2023 Andrey Semashev +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Tests that boost::swap propagates noexcept specification correctly + +#include +#include + +#if !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_CXX11_STATIC_ASSERT) && \ + !(defined(BOOST_GCC) && (BOOST_GCC < 40700)) + +namespace test_ns { + +struct class_with_noexcept_swap +{ + static class_with_noexcept_swap& instance() noexcept; + + friend void swap(class_with_noexcept_swap&, class_with_noexcept_swap&) noexcept + { + } +}; + +struct class_with_except_swap +{ + static class_with_except_swap& instance() noexcept; + + friend void swap(class_with_except_swap&, class_with_except_swap&) + { + } +}; + +} // namespace test_ns + +static_assert(noexcept(boost::swap(test_ns::class_with_noexcept_swap::instance(), test_ns::class_with_noexcept_swap::instance())), + "boost::swap for class_with_noexcept_swap should have noexcept specification"); +static_assert(!noexcept(boost::swap(test_ns::class_with_except_swap::instance(), test_ns::class_with_except_swap::instance())), + "boost::swap for class_with_except_swap should not have noexcept specification"); + +#endif // !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_CXX11_STATIC_ASSERT) ... From eda68d40862506466d68ff3059089f8a3ff969b7 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 7 Jan 2023 01:54:22 +0300 Subject: [PATCH 257/258] Trim trailing spaces in boost::swap tests. --- test/swap/swap_array_of_class.cpp | 4 ++-- test/swap/swap_array_of_int.cpp | 4 ++-- test/swap/swap_array_of_template.cpp | 4 ++-- test/swap/swap_const_wrapper_fail.cpp | 6 +++--- test/swap/swap_specialized_in_boost.cpp | 2 +- test/swap/swap_specialized_in_boost_and_other.cpp | 6 +++--- test/swap/swap_specialized_in_global.cpp | 4 ++-- test/swap/swap_specialized_in_other.cpp | 4 ++-- test/swap/swap_specialized_in_std.cpp | 4 ++-- test/swap/swap_std_typeinfo_ptr.cpp | 2 +- test/swap/swap_std_vector_of_boost.cpp | 8 ++++---- test/swap/swap_std_vector_of_global.cpp | 8 ++++---- test/swap/swap_std_vector_of_other.cpp | 6 +++--- test/swap/swap_test_class.hpp | 10 +++++----- 14 files changed, 36 insertions(+), 36 deletions(-) diff --git a/test/swap/swap_array_of_class.cpp b/test/swap/swap_array_of_class.cpp index 245602d..b8b496a 100644 --- a/test/swap/swap_array_of_class.cpp +++ b/test/swap/swap_array_of_class.cpp @@ -46,13 +46,13 @@ int main() const std::size_t array_size = 2; const swap_test_class initial_array1[array_size] = { swap_test_class(1), swap_test_class(2) }; const swap_test_class initial_array2[array_size] = { swap_test_class(3), swap_test_class(4) }; - + swap_test_class array1[array_size]; swap_test_class array2[array_size]; std::copy(initial_array1, initial_array1 + array_size, array1); std::copy(initial_array2, initial_array2 + array_size, array2); - + swap_test_class::reset(); boost::swap(array1, array2); diff --git a/test/swap/swap_array_of_int.cpp b/test/swap/swap_array_of_int.cpp index e8285e0..1978d90 100644 --- a/test/swap/swap_array_of_int.cpp +++ b/test/swap/swap_array_of_int.cpp @@ -20,13 +20,13 @@ int main() const std::size_t array_size = 3; const int initial_array1[array_size] = { 1, 2, 3 }; const int initial_array2[array_size] = { 4, 5, 6 }; - + int array1[array_size]; int array2[array_size]; std::copy(initial_array1, initial_array1 + array_size, array1); std::copy(initial_array2, initial_array2 + array_size, array2); - + boost::swap(array1, array2); BOOST_CHECK(std::equal(array1, array1 + array_size, initial_array2)); diff --git a/test/swap/swap_array_of_template.cpp b/test/swap/swap_array_of_template.cpp index 1ec33fd..652d418 100644 --- a/test/swap/swap_array_of_template.cpp +++ b/test/swap/swap_array_of_template.cpp @@ -52,13 +52,13 @@ int main() const std::size_t array_size = 2; const swap_test_template initial_array1[array_size] = { { swap_test_class(1) }, { swap_test_class(2) } }; const swap_test_template initial_array2[array_size] = { { swap_test_class(3) }, { swap_test_class(4) } }; - + swap_test_template array1[array_size]; swap_test_template array2[array_size]; std::copy(initial_array1, initial_array1 + array_size, array1); std::copy(initial_array2, initial_array2 + array_size, array2); - + swap_test_class::reset(); boost::swap(array1, array2); diff --git a/test/swap/swap_const_wrapper_fail.cpp b/test/swap/swap_const_wrapper_fail.cpp index da2e4c6..ea44a4d 100644 --- a/test/swap/swap_const_wrapper_fail.cpp +++ b/test/swap/swap_const_wrapper_fail.cpp @@ -6,7 +6,7 @@ namespace boost { - + template struct Wrapper { T value; @@ -16,9 +16,9 @@ template inline void swap( Wrapper & w, Wrapper & v ) { boost::swap( w, v ); } - + } // namespace boost - + int main() { boost::Wrapper const w = { 2 }; diff --git a/test/swap/swap_specialized_in_boost.cpp b/test/swap/swap_specialized_in_boost.cpp index dcb015d..ab74b5e 100644 --- a/test/swap/swap_specialized_in_boost.cpp +++ b/test/swap/swap_specialized_in_boost.cpp @@ -31,7 +31,7 @@ int main() boost::swap_test_class object1 = initial_value1; boost::swap_test_class object2 = initial_value2; - + boost::swap_test_class::reset(); boost::swap(object1,object2); diff --git a/test/swap/swap_specialized_in_boost_and_other.cpp b/test/swap/swap_specialized_in_boost_and_other.cpp index d596775..3f874bc 100644 --- a/test/swap/swap_specialized_in_boost_and_other.cpp +++ b/test/swap/swap_specialized_in_boost_and_other.cpp @@ -10,7 +10,7 @@ // in an other namespace to have a custom swap function in boost, because the // boost::swap utility should find the swap function in the other namespace, by // argument dependent lookup (ADL). Unfortunately ADL isn't fully implemented -// by some specific compiler versions, including Intel C++ 8.1, MSVC 7.1, and +// by some specific compiler versions, including Intel C++ 8.1, MSVC 7.1, and // Borland 5.9.3. Users of those compilers might consider adding a swap overload // to the boost namespace. @@ -50,13 +50,13 @@ int main() other::swap_test_class object1 = initial_value1; other::swap_test_class object2 = initial_value2; - + other::swap_test_class::reset(); boost::swap(object1,object2); BOOST_CHECK(object1 == initial_value2); BOOST_CHECK(object2 == initial_value1); - + BOOST_CHECK_EQUAL(other::swap_test_class::swap_count(),1); BOOST_CHECK_EQUAL(other::swap_test_class::copy_count(),0); diff --git a/test/swap/swap_specialized_in_global.cpp b/test/swap/swap_specialized_in_global.cpp index 8b0f10a..72eb15c 100644 --- a/test/swap/swap_specialized_in_global.cpp +++ b/test/swap/swap_specialized_in_global.cpp @@ -25,13 +25,13 @@ int main() swap_test_class object1 = initial_value1; swap_test_class object2 = initial_value2; - + swap_test_class::reset(); boost::swap(object1,object2); BOOST_CHECK(object1 == initial_value2); BOOST_CHECK(object2 == initial_value1); - + BOOST_CHECK_EQUAL(swap_test_class::swap_count(),1); BOOST_CHECK_EQUAL(swap_test_class::copy_count(),0); diff --git a/test/swap/swap_specialized_in_other.cpp b/test/swap/swap_specialized_in_other.cpp index 016cc8a..74240fc 100644 --- a/test/swap/swap_specialized_in_other.cpp +++ b/test/swap/swap_specialized_in_other.cpp @@ -31,13 +31,13 @@ int main() other::swap_test_class object1 = initial_value1; other::swap_test_class object2 = initial_value2; - + other::swap_test_class::reset(); boost::swap(object1,object2); BOOST_CHECK(object1 == initial_value2); BOOST_CHECK(object2 == initial_value1); - + BOOST_CHECK_EQUAL(other::swap_test_class::swap_count(),1); BOOST_CHECK_EQUAL(other::swap_test_class::copy_count(),0); diff --git a/test/swap/swap_specialized_in_std.cpp b/test/swap/swap_specialized_in_std.cpp index 62d4ee4..6be5e77 100644 --- a/test/swap/swap_specialized_in_std.cpp +++ b/test/swap/swap_specialized_in_std.cpp @@ -30,13 +30,13 @@ int main() swap_test_class object1 = initial_value1; swap_test_class object2 = initial_value2; - + swap_test_class::reset(); boost::swap(object1,object2); BOOST_CHECK(object1 == initial_value2); BOOST_CHECK(object2 == initial_value1); - + BOOST_CHECK_EQUAL(swap_test_class::swap_count(),1); BOOST_CHECK_EQUAL(swap_test_class::copy_count(),0); diff --git a/test/swap/swap_std_typeinfo_ptr.cpp b/test/swap/swap_std_typeinfo_ptr.cpp index 10fd6e5..dfd35a5 100644 --- a/test/swap/swap_std_typeinfo_ptr.cpp +++ b/test/swap/swap_std_typeinfo_ptr.cpp @@ -19,7 +19,7 @@ int main() { const std::type_info * const initial_value1 = 0; const std::type_info * const initial_value2 = &typeid(double); - + const std::type_info * ptr1 = initial_value1; const std::type_info * ptr2 = initial_value2; diff --git a/test/swap/swap_std_vector_of_boost.cpp b/test/swap/swap_std_vector_of_boost.cpp index 93d5d61..e2badc5 100644 --- a/test/swap/swap_std_vector_of_boost.cpp +++ b/test/swap/swap_std_vector_of_boost.cpp @@ -5,7 +5,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // Tests swapping std::vector objects by means of boost::swap, -// having boost::swap_test_class as vector element type. +// having boost::swap_test_class as vector element type. #include #include @@ -39,12 +39,12 @@ int main() const vector_type initial_value1(initial_size1, swap_test_class_type(1)); const vector_type initial_value2(initial_size2, swap_test_class_type(2)); - + vector_type object1 = initial_value1; vector_type object2 = initial_value2; swap_test_class_type::reset(); - + boost::swap(object1,object2); BOOST_CHECK_EQUAL(object1.size(),initial_size2); @@ -52,7 +52,7 @@ int main() BOOST_CHECK(object1 == initial_value2); BOOST_CHECK(object2 == initial_value1); - + BOOST_CHECK_EQUAL(swap_test_class_type::swap_count(),0); BOOST_CHECK_EQUAL(swap_test_class_type::copy_count(),0); diff --git a/test/swap/swap_std_vector_of_global.cpp b/test/swap/swap_std_vector_of_global.cpp index 08d6974..11fe9b3 100644 --- a/test/swap/swap_std_vector_of_global.cpp +++ b/test/swap/swap_std_vector_of_global.cpp @@ -5,7 +5,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // Tests swapping std::vector objects by means of boost::swap, -// having ::swap_test_class as vector element type. +// having ::swap_test_class as vector element type. #include #include @@ -17,7 +17,7 @@ //Put test class in the global namespace #include "./swap_test_class.hpp" -//Provide swap function in the global namespace +//Provide swap function in the global namespace void swap(swap_test_class& left, swap_test_class& right) { left.swap(right); @@ -32,12 +32,12 @@ int main() const vector_type initial_value1(initial_size1, swap_test_class(1)); const vector_type initial_value2(initial_size2, swap_test_class(2)); - + vector_type object1 = initial_value1; vector_type object2 = initial_value2; swap_test_class::reset(); - + boost::swap(object1,object2); BOOST_CHECK_EQUAL(object1.size(),initial_size2); diff --git a/test/swap/swap_std_vector_of_other.cpp b/test/swap/swap_std_vector_of_other.cpp index 77a3525..a713767 100644 --- a/test/swap/swap_std_vector_of_other.cpp +++ b/test/swap/swap_std_vector_of_other.cpp @@ -5,7 +5,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // Tests swapping std::vector objects by means of boost::swap, -// having other::swap_test_class as vector element type. +// having other::swap_test_class as vector element type. #include #include @@ -39,12 +39,12 @@ int main() const vector_type initial_value1(initial_size1, swap_test_class_type(1)); const vector_type initial_value2(initial_size2, swap_test_class_type(2)); - + vector_type object1 = initial_value1; vector_type object2 = initial_value2; swap_test_class_type::reset(); - + boost::swap(object1,object2); BOOST_CHECK_EQUAL(object1.size(),initial_size2); diff --git a/test/swap/swap_test_class.hpp b/test/swap/swap_test_class.hpp index a25dbbd..a36bd41 100644 --- a/test/swap/swap_test_class.hpp +++ b/test/swap/swap_test_class.hpp @@ -59,7 +59,7 @@ public: { m_data = arg; } - + static unsigned int swap_count(){ return swapCount(); } static unsigned int copy_count(){ return copyCount(); } static unsigned int construct_count(){ return constructCount(); } @@ -68,7 +68,7 @@ public: static void reset() { swapCount() = 0; - copyCount() = 0; + copyCount() = 0; constructCount() = 0; destructCount() = 0; } @@ -80,19 +80,19 @@ private: return value; } - static unsigned int& copyCount() + static unsigned int& copyCount() { static unsigned int value = 0; return value; } - static unsigned int& constructCount() + static unsigned int& constructCount() { static unsigned int value = 0; return value; } - static unsigned int& destructCount() + static unsigned int& destructCount() { static unsigned int value = 0; return value; From 0890785fec250b55c2d6521615968113477012ce Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 7 Jan 2023 03:52:46 +0300 Subject: [PATCH 258/258] Added #pragma once in swap.hpp. --- include/boost/core/swap.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/boost/core/swap.hpp b/include/boost/core/swap.hpp index 9952779..7add2fb 100644 --- a/include/boost/core/swap.hpp +++ b/include/boost/core/swap.hpp @@ -30,6 +30,10 @@ #endif #include // for std::size_t +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + #if defined(BOOST_GCC) && (BOOST_GCC < 40700) // gcc 4.6 ICEs on noexcept specifications below #define BOOST_CORE_SWAP_NOEXCEPT_IF(x) @@ -82,4 +86,4 @@ namespace boost #undef BOOST_CORE_SWAP_NOEXCEPT_IF -#endif +#endif // BOOST_CORE_SWAP_HPP