diff --git a/doc/container.qbk b/doc/container.qbk index a4c3056..d2ba3db 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1341,6 +1341,11 @@ use [*Boost.Container]? There are several reasons for that: [section:release_notes_boost_1_76_00 Boost 1.76 Release] * Added [[no-discard]] attribute in all containers to catch bugs related to unused return values. + +* Replaced default standard exception classes with Boost.Container own classes, reducing considerably the included files overhead. + Example: in MSVC 19 `boost/container/vector.hpp` preprocessed file size reduces from 1,5MB to 930KB. If you still want to use + standard exception classes, you can define `BOOST_CONTAINER_USE_STD_EXCEPTIONS` before using any Boost.Container class. + * Fixed bugs/issues: * [@https://github.com/boostorg/container/issues/139 GitHub #139: ['"flat_map merge and iterators"]]. * [@https://github.com/boostorg/container/issues/141 GitHub #141: ['"small_vector does not propagate no throw properties of move operation of contained type"]]. diff --git a/include/boost/container/detail/workaround.hpp b/include/boost/container/detail/workaround.hpp index f7d08cb..05ca08c 100644 --- a/include/boost/container/detail/workaround.hpp +++ b/include/boost/container/detail/workaround.hpp @@ -151,4 +151,13 @@ #endif #endif + +//Configuration options: + +//Define this to use std exception types instead of boost::container's own exception types +//#define BOOST_CONTAINER_USE_STD_EXCEPTIONS + + + + #endif //#ifndef BOOST_CONTAINER_DETAIL_WORKAROUND_HPP diff --git a/include/boost/container/throw_exception.hpp b/include/boost/container/throw_exception.hpp index e2a0f6a..5ab7d12 100644 --- a/include/boost/container/throw_exception.hpp +++ b/include/boost/container/throw_exception.hpp @@ -24,9 +24,102 @@ #include #ifndef BOOST_NO_EXCEPTIONS +#include //for std exception base + +# if defined(BOOST_CONTAINER_USE_STD_EXCEPTIONS) #include //for std exception types #include //for implicit std::string conversion #include //for std::bad_alloc + +typedef std::bad_alloc bad_alloc_t; +typedef std::out_of_range out_of_range_t; +typedef std::out_of_range length_error_t; +typedef std::logic_error logic_error_t; +typedef std::runtime_error runtime_error_t; + +# else //!BOOST_CONTAINER_USE_STD_EXCEPTIONS + +namespace boost { +namespace container { + +class exception + : public ::std::exception +{ + typedef ::std::exception std_exception_t; + + public: + + //msg must be a static string (guaranteed by callers) + explicit exception(const char *msg) + : std_exception_t(), m_msg(msg) + {} + + virtual const char *what() const BOOST_NOEXCEPT_OR_NOTHROW + { return m_msg ? m_msg : "unknown boost::container exception"; } + + private: + const char *m_msg; +}; + +class bad_alloc + : public exception +{ + public: + bad_alloc() + : exception("boost::container::bad_alloc thrown") + {} +}; + +typedef bad_alloc bad_alloc_t; + +class out_of_range + : public exception +{ + public: + explicit out_of_range(const char *msg) + : exception(msg) + {} +}; + +typedef out_of_range out_of_range_t; + +class length_error + : public exception +{ + public: + explicit length_error(const char *msg) + : exception(msg) + {} +}; + +typedef out_of_range length_error_t; + +class logic_error + : public exception +{ + public: + explicit logic_error(const char *msg) + : exception(msg) + {} +}; + +typedef logic_error logic_error_t; + +class runtime_error + : public exception +{ + public: + explicit runtime_error(const char *msg) + : exception(msg) + {} +}; + +typedef runtime_error runtime_error_t; + +} // namespace boost { +} // namespace container { + +# endif #else #include #include //for std::abort @@ -99,7 +192,11 @@ namespace container { //! BOOST_NORETURN inline void throw_bad_alloc() { + #ifdef BOOST_CONTAINER_USE_STD_EXCEPTIONS throw std::bad_alloc(); + #else + throw bad_alloc(); + #endif } //! Exception callback called by Boost.Container to signal arguments out of range. @@ -115,7 +212,11 @@ namespace container { //! BOOST_NORETURN inline void throw_out_of_range(const char* str) { + #ifdef BOOST_CONTAINER_USE_STD_EXCEPTIONS throw std::out_of_range(str); + #else + throw out_of_range(str); + #endif } //! Exception callback called by Boost.Container to signal errors resizing. @@ -131,7 +232,11 @@ namespace container { //! BOOST_NORETURN inline void throw_length_error(const char* str) { + #ifdef BOOST_CONTAINER_USE_STD_EXCEPTIONS throw std::length_error(str); + #else + throw length_error(str); + #endif } //! Exception callback called by Boost.Container to report errors in the internal logical @@ -148,7 +253,11 @@ namespace container { //! BOOST_NORETURN inline void throw_logic_error(const char* str) { + #ifdef BOOST_CONTAINER_USE_STD_EXCEPTIONS throw std::logic_error(str); + #else + throw logic_error(str); + #endif } //! Exception callback called by Boost.Container to report errors that can only be detected during runtime. @@ -164,7 +273,11 @@ namespace container { //! BOOST_NORETURN inline void throw_runtime_error(const char* str) { + #ifdef BOOST_CONTAINER_USE_STD_EXCEPTIONS throw std::runtime_error(str); + #else + throw runtime_error(str); + #endif } #endif diff --git a/src/global_resource.cpp b/src/global_resource.cpp index 015531f..a7b77c2 100644 --- a/src/global_resource.cpp +++ b/src/global_resource.cpp @@ -52,7 +52,12 @@ struct null_memory_resource_imp void* do_allocate(std::size_t bytes, std::size_t alignment) BOOST_OVERRIDE { (void)bytes; (void)alignment; + #if defined(BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS) || defined(BOOST_NO_EXCEPTIONS) throw_bad_alloc(); + #else + throw std::bad_alloc(); + #endif + return 0; } diff --git a/src/monotonic_buffer_resource.cpp b/src/monotonic_buffer_resource.cpp index c676992..f625f65 100644 --- a/src/monotonic_buffer_resource.cpp +++ b/src/monotonic_buffer_resource.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -135,8 +136,14 @@ void *monotonic_buffer_resource::allocate_from_current(std::size_t aligner, std: void* monotonic_buffer_resource::do_allocate(std::size_t bytes, std::size_t alignment) { - if(alignment > memory_resource::max_align) + if(alignment > memory_resource::max_align){ + (void)bytes; (void)alignment; + #if defined(BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS) || defined(BOOST_NO_EXCEPTIONS) throw_bad_alloc(); + #else + throw std::bad_alloc(); + #endif + } //See if there is room in current buffer std::size_t aligner = 0u; diff --git a/test/devector_test.cpp b/test/devector_test.cpp index ce86ec3..ce0aca0 100644 --- a/test/devector_test.cpp +++ b/test/devector_test.cpp @@ -1844,7 +1844,7 @@ template void test_at() a.at(0) = T(100); BOOST_TEST(a.at(0) == 100); - BOOST_TEST_THROWS((void)a.at(3), std::out_of_range); + BOOST_TEST_THROWS((void)a.at(3), out_of_range_t); } { // const at @@ -1853,7 +1853,7 @@ template void test_at() BOOST_TEST(a.at(0) == 1); - BOOST_TEST_THROWS((void)a.at(3), std::out_of_range); + BOOST_TEST_THROWS((void)a.at(3), out_of_range_t); } #endif //#ifndef BOOST_NO_EXCEPTIONS } diff --git a/test/static_vector_options_test.cpp b/test/static_vector_options_test.cpp index 80e8843..6a045ac 100644 --- a/test/static_vector_options_test.cpp +++ b/test/static_vector_options_test.cpp @@ -90,7 +90,7 @@ void test_throw_on_overflow() BOOST_TRY{ v.push_back(0); } - BOOST_CATCH(std::bad_alloc&) + BOOST_CATCH(bad_alloc_t&) { expected_type_thrown = true; } diff --git a/test/static_vector_test.cpp b/test/static_vector_test.cpp index cf61791..5f18e26 100644 --- a/test/static_vector_test.cpp +++ b/test/static_vector_test.cpp @@ -25,7 +25,7 @@ void test_ctor_ndc() BOOST_TEST_EQ(s.size() , 0u); BOOST_TEST(s.capacity() == N); BOOST_TEST(s.max_size() == N); - BOOST_TEST_THROWS( (void)s.at(0u), std::out_of_range ); + BOOST_TEST_THROWS( (void)s.at(0u), out_of_range_t); } template @@ -36,7 +36,7 @@ void test_ctor_nc(size_t n) BOOST_TEST(s.size() == n); BOOST_TEST(s.capacity() == N); BOOST_TEST(s.max_size() == N); - BOOST_TEST_THROWS( (void)s.at(n), std::out_of_range ); + BOOST_TEST_THROWS( (void)s.at(n), out_of_range_t); if ( 1 < n ) { s[0] = 10; @@ -55,7 +55,7 @@ void test_ctor_nd(size_t n, T const& v) BOOST_STATIC_ASSERT((static_vector::static_capacity) == N); BOOST_TEST(s.size() == n); BOOST_TEST(s.capacity() == N); - BOOST_TEST_THROWS( (void)s.at(n), std::out_of_range ); + BOOST_TEST_THROWS( (void)s.at(n), out_of_range_t); if ( 1 < n ) { BOOST_TEST(v == s[0]); @@ -80,7 +80,7 @@ void test_support_for_initializer_list() BOOST_TEST(10 == sv[0]); BOOST_TEST(8 == sv[1]); - BOOST_TEST_THROWS(sv_cap_2({1, 1, 1}), std::bad_alloc); + BOOST_TEST_THROWS(sv_cap_2({1, 1, 1}), bad_alloc_t); } { @@ -89,10 +89,10 @@ void test_support_for_initializer_list() BOOST_TEST(1 == sv[0]); BOOST_TEST(2 == sv[1]); - BOOST_TEST_THROWS(sv.assign({1, 2, 3}), std::bad_alloc); + BOOST_TEST_THROWS(sv.assign({1, 2, 3}), bad_alloc_t); static_vector greaterThanSv = {1, 2, 3}; - BOOST_TEST_THROWS(sv = greaterThanSv, std::bad_alloc); + BOOST_TEST_THROWS(sv = greaterThanSv, bad_alloc_t); } { @@ -101,7 +101,7 @@ void test_support_for_initializer_list() BOOST_TEST(99 == sv[0]); BOOST_TEST(95 == sv[1]); - BOOST_TEST_THROWS(sv.insert(sv.begin(), {101, 102, 103}), std::bad_alloc); + BOOST_TEST_THROWS(sv.insert(sv.begin(), {101, 102, 103}), bad_alloc_t); } #endif } @@ -114,7 +114,7 @@ void test_resize_nc(size_t n) s.resize(n); BOOST_TEST(s.size() == n); BOOST_TEST(s.capacity() == N); - BOOST_TEST_THROWS( (void)s.at(n), std::out_of_range ); + BOOST_TEST_THROWS( (void)s.at(n), out_of_range_t); if ( 1 < n ) { s[0] = 10; @@ -134,7 +134,7 @@ void test_resize_nd(size_t n, T const& v) s.resize(n, v); BOOST_TEST(s.size() == n); BOOST_TEST(s.capacity() == N); - BOOST_TEST_THROWS( (void)s.at(n), std::out_of_range ); + BOOST_TEST_THROWS( (void)s.at(n), out_of_range_t); if ( 1 < n ) { BOOST_TEST(v == s[0]); @@ -156,14 +156,14 @@ void test_push_back_nd() static_vector s; BOOST_TEST(s.size() == 0); - BOOST_TEST_THROWS( (void)s.at(0), std::out_of_range ); + BOOST_TEST_THROWS( (void)s.at(0), out_of_range_t); for ( size_t i = 0 ; i < N ; ++i ) { T t(static_cast(i)); s.push_back(t); BOOST_TEST(s.size() == i + 1); - BOOST_TEST_THROWS( (void)s.at(i + 1), std::out_of_range ); + BOOST_TEST_THROWS( (void)s.at(i + 1), out_of_range_t); BOOST_TEST(T((int)i) == s.at(i)); BOOST_TEST(T((int)i) == s[i]); BOOST_TEST(T((int)i) == s.back()); @@ -187,7 +187,7 @@ void test_pop_back_nd() { s.pop_back(); BOOST_TEST(s.size() == i - 1); - BOOST_TEST_THROWS( (void)s.at(i - 1), std::out_of_range ); + BOOST_TEST_THROWS( (void)s.at(i - 1), out_of_range_t); BOOST_TEST(T((int)i - 2) == s.at(i - 2)); BOOST_TEST(T((int)i - 2) == s[i - 2]); BOOST_TEST(T((int)i - 2) == s.back()); @@ -418,17 +418,17 @@ void test_capacity_0_nd() static_vector_0_t s; BOOST_TEST(s.size() == 0); BOOST_TEST(s.capacity() == 0); - BOOST_TEST_THROWS((void)s.at(0), std::out_of_range); - BOOST_TEST_THROWS(s.resize(5u, T(0)), std::bad_alloc); - BOOST_TEST_THROWS(s.push_back(T(0)), std::bad_alloc); - BOOST_TEST_THROWS(s.insert(s.end(), T(0)), std::bad_alloc); - BOOST_TEST_THROWS(s.insert(s.end(), 5u, T(0)), std::bad_alloc); - BOOST_TEST_THROWS(s.insert(s.end(), v.begin(), v.end()), std::bad_alloc); - BOOST_TEST_THROWS(s.assign(v.begin(), v.end()), std::bad_alloc); - BOOST_TEST_THROWS(s.assign(5u, T(0)), std::bad_alloc); - BOOST_TEST_THROWS(s.assign(5u, T(0)), std::bad_alloc); - BOOST_TEST_THROWS(static_vector_0_t s2(v.begin(), v.end()), std::bad_alloc); - BOOST_TEST_THROWS(static_vector_0_t s1(5u, T(0)), std::bad_alloc); + BOOST_TEST_THROWS((void)s.at(0), out_of_range_t); + BOOST_TEST_THROWS(s.resize(5u, T(0)), bad_alloc_t); + BOOST_TEST_THROWS(s.push_back(T(0)), bad_alloc_t); + BOOST_TEST_THROWS(s.insert(s.end(), T(0)), bad_alloc_t); + BOOST_TEST_THROWS(s.insert(s.end(), 5u, T(0)), bad_alloc_t); + BOOST_TEST_THROWS(s.insert(s.end(), v.begin(), v.end()), bad_alloc_t); + BOOST_TEST_THROWS(s.assign(v.begin(), v.end()), bad_alloc_t); + BOOST_TEST_THROWS(s.assign(5u, T(0)), bad_alloc_t); + BOOST_TEST_THROWS(s.assign(5u, T(0)), bad_alloc_t); + BOOST_TEST_THROWS(static_vector_0_t s2(v.begin(), v.end()), bad_alloc_t); + BOOST_TEST_THROWS(static_vector_0_t s1(5u, T(0)), bad_alloc_t); } template @@ -438,15 +438,15 @@ void test_exceptions_nd() typedef static_vector static_vector_n_half_t; static_vector_n_half_t s(N/2, T(0)); - BOOST_TEST_THROWS(s.resize(N, T(0)), std::bad_alloc); - BOOST_TEST_THROWS(s.push_back(T(0)), std::bad_alloc); - BOOST_TEST_THROWS(s.insert(s.end(), T(0)), std::bad_alloc); - BOOST_TEST_THROWS(s.insert(s.end(), 1, T(0)), std::bad_alloc); - BOOST_TEST_THROWS(s.insert(s.end(), v.begin(), v.end()), std::bad_alloc); - BOOST_TEST_THROWS(s.assign(v.begin(), v.end()), std::bad_alloc); - BOOST_TEST_THROWS(s.assign(N, T(0)), std::bad_alloc); - BOOST_TEST_THROWS(static_vector_n_half_t s2(v.begin(), v.end()), std::bad_alloc); - BOOST_TEST_THROWS(static_vector_n_half_t s1(N/2+1, T(0)), std::bad_alloc); + BOOST_TEST_THROWS(s.resize(N, T(0)), bad_alloc_t); + BOOST_TEST_THROWS(s.push_back(T(0)), bad_alloc_t); + BOOST_TEST_THROWS(s.insert(s.end(), T(0)), bad_alloc_t); + BOOST_TEST_THROWS(s.insert(s.end(), 1, T(0)), bad_alloc_t); + BOOST_TEST_THROWS(s.insert(s.end(), v.begin(), v.end()), bad_alloc_t); + BOOST_TEST_THROWS(s.assign(v.begin(), v.end()), bad_alloc_t); + BOOST_TEST_THROWS(s.assign(N, T(0)), bad_alloc_t); + BOOST_TEST_THROWS(static_vector_n_half_t s2(v.begin(), v.end()), bad_alloc_t); + BOOST_TEST_THROWS(static_vector_n_half_t s1(N/2+1, T(0)), bad_alloc_t); } template @@ -541,12 +541,12 @@ void test_swap_and_move_nd() typedef static_vector small_vector_t; static_vector v(N, T(0)); small_vector_t s(N/2, T(1)); - BOOST_TEST_THROWS(s.swap(v), std::bad_alloc); + BOOST_TEST_THROWS(s.swap(v), bad_alloc_t); v.resize(N, T(0)); - BOOST_TEST_THROWS(s = boost::move(v), std::bad_alloc); - BOOST_TEST_THROWS(s = v, std::bad_alloc); + BOOST_TEST_THROWS(s = boost::move(v), bad_alloc_t); + BOOST_TEST_THROWS(s = v, bad_alloc_t); v.resize(N, T(0)); - BOOST_TEST_THROWS(small_vector_t s2(boost::move(v)), std::bad_alloc); + BOOST_TEST_THROWS(small_vector_t s2(boost::move(v)), bad_alloc_t); } } @@ -560,7 +560,7 @@ void test_emplace_0p() for (int i = 0 ; i < int(N) ; ++i ) v.emplace_back(); BOOST_TEST(v.size() == N); - BOOST_TEST_THROWS(v.emplace_back(), std::bad_alloc); + BOOST_TEST_THROWS(v.emplace_back(), bad_alloc_t); } } @@ -574,7 +574,7 @@ void test_emplace_2p() for (int i = 0 ; i < int(N) ; ++i ) v.emplace_back(i, 100 + i); BOOST_TEST(v.size() == N); - BOOST_TEST_THROWS(v.emplace_back((int)N, 100 + (int)N), std::bad_alloc); + BOOST_TEST_THROWS(v.emplace_back((int)N, 100 + (int)N), bad_alloc_t); BOOST_TEST(v.size() == N); for (int i = 0 ; i < int(N) ; ++i ) BOOST_TEST(v[i] == T(i, 100 + i));