- Replaced default standard exception classes with Boost.Container own classes, reducing considerably the included files overhead

This commit is contained in:
Ion Gaztañaga
2020-12-30 15:07:32 +01:00
parent b17dabf47a
commit d5a830434e
8 changed files with 181 additions and 42 deletions

View File

@ -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"]].

View File

@ -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

View File

@ -24,9 +24,102 @@
#include <boost/core/ignore_unused.hpp>
#ifndef BOOST_NO_EXCEPTIONS
#include <exception> //for std exception base
# if defined(BOOST_CONTAINER_USE_STD_EXCEPTIONS)
#include <stdexcept> //for std exception types
#include <string> //for implicit std::string conversion
#include <new> //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 <boost/assert.hpp>
#include <cstdlib> //for std::abort
@ -99,7 +192,11 @@ namespace container {
//! </ul>
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 {
//! </ul>
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 {
//! </ul>
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 {
//! </ul>
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 {
//! </ul>
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

View File

@ -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;
}

View File

@ -18,6 +18,7 @@
#include <boost/container/detail/min_max.hpp>
#include <boost/intrusive/detail/math.hpp>
#include <boost/container/throw_exception.hpp>
#include <new>
#include <cstddef>
@ -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;

View File

@ -1844,7 +1844,7 @@ template <class Devector> 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 <class Devector> 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
}

View File

@ -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;
}

View File

@ -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 <typename T, size_t N>
@ -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<T, N>::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<int, 3> 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<T, N> 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<int>(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 <typename T, size_t N>
@ -438,15 +438,15 @@ void test_exceptions_nd()
typedef static_vector<T, N/2> 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 <typename T, size_t N>
@ -541,12 +541,12 @@ void test_swap_and_move_nd()
typedef static_vector<T, N/2> small_vector_t;
static_vector<T, N> 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));