diff --git a/doc/container.qbk b/doc/container.qbk index 7dbc319..5b90af6 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -189,6 +189,49 @@ Finally, we can just compile, link, and run! [endsect] +[section:exception_handling Boost.Container and C++ exceptions] + +In some environments, such as game development or embedded systems, C++ exceptions are disabled or a customized error handling is needed. +According to document [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2271.html N2271 EASTL -- Electronic Arts Standard Template Library] +exceptions can be disabled for several reasons: + +* ["['Exception handling incurs some kind of cost in all compiler implementations, including those that avoid + the cost during normal execution. However, in some cases this cost may arguably offset the cost of the code that it is replacing.]] +* ["['Exception handling is often agreed to be a superior solution for handling a large range of function return values. However, + avoiding the creation of functions that need large ranges of return values is superior to using exception handling to handle such values.]] +* ["['Using exception handling correctly can be difficult in the case of complex software.]] +* ["['The execution of throw and catch can be significantly expensive with some implementations.]] +* ["['Exception handling violates the don't-pay-for-what-you-don't-use design of C++, as it incurs overhead in any non-leaf function that + has destructible stack objects regardless of whether they use exception handling.]] +* ["['The approach that game software usually takes is to avoid the need for exception handling where possible; avoid the possibility + of circumstances that may lead to exceptions. For example, verify up front that there is enough memory for a subsystem to do its job + instead of trying to deal with the problem via exception handling or any other means after it occurs.]] +* ["['However, some game libraries may nevertheless benefit from the use of exception handling. It's best, however, + if such libraries keep the exception handling internal lest they force their usage of exception handling on the rest of the application.]] + +In order to support environments without C++ exception support or environments with special error handling needs, +[*Boost.Container] changes error signalling behaviour when `BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS` or `BOOST_NO_EXCEPTIONS` +is defined. The former shall be defined by the user and the latter can be either defined by the user or implicitly defined by [*Boost.Confg] +when the compiler has been invoked with the appropriate flag (like `-fno-exceptions` in GCC). + +When dealing with user-defined classes, (e.g. when constructing user-defined classes): + +* If `BOOST_NO_EXCEPTIONS` is defined, the library avoids using `try`/`catch`/`throw` statements. The class writer must handle and + propagate error situations internally as no error will be propagated through [*Boost.Container]. +* If `BOOST_NO_EXCEPTIONS` is *not* defined, the library propagates exceptions offering the exception guarantees detailed in the documentation. + +When the library needs to throw an exception (such as `out_of_range` when an incorrect index is used in `vector::at`)], the library calls +a throw callback declared in ``: + +* If `BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS` is defined, then the programmer must provide its own definition for all + `throw_xxx` functions. Those functions can't return, they must throw an exception or call `std::exit` or `std::abort`. +* Else if `BOOST_NO_EXCEPTIONS` is defined, a `BOOST_ASSERT_MSG` assertion is triggered + (see [@http://www.boost.org/libs/utility/assert.html Boost.Assert] for more information). + If this assertion returns, then `std::abort` is called. +* Else, an appropriate standard library exception is thrown (like `std::out_of_range`). + +[endsect] + [section:non_standard_containers Non-standard containers] [section:stable_vector ['stable_vector]] @@ -569,6 +612,8 @@ use [*Boost.Container]? There are several reasons for that: usually implies a no-throw guarantee (if predicate's or allocator's default constructor doesn't throw). * Small string optimization for [classref boost::container::basic_string basic_string]. * New extensions beyond the standard based on user feedback to improve code performance. +* You need a portable implementation that works when compiling without exceptions support or + you need to customize the error handling when a container needs to signall an exceptional error. [endsect] @@ -614,6 +659,12 @@ use [*Boost.Container]? There are several reasons for that: [section:release_notes Release Notes] +[section:release_notes_boost_1_54_00 Boost 1.54 Release] + +* Support for `BOOST_NO_EXCEPTIONS` [@https://svn.boost.org/trac/boost/ticket/7227 #7227]. + +[endsect] + [section:release_notes_boost_1_53_00 Boost 1.53 Release] * Fixed bug [@https://svn.boost.org/trac/boost/ticket/7650 #7650]. diff --git a/include/boost/container/deque.hpp b/include/boost/container/deque.hpp index 32fa480..0962f0b 100644 --- a/include/boost/container/deque.hpp +++ b/include/boost/container/deque.hpp @@ -46,12 +46,12 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include #include @@ -1575,7 +1575,7 @@ class deque : protected deque_base } void priv_range_check(size_type n) const - { if (n >= this->size()) BOOST_RETHROW std::out_of_range("deque"); } + { if (n >= this->size()) throw_out_of_range("deque::at out of range"); } template iterator priv_insert(const_iterator position, BOOST_FWD_REF(U) x) diff --git a/include/boost/container/detail/adaptive_node_pool_impl.hpp b/include/boost/container/detail/adaptive_node_pool_impl.hpp index 42bdf43..8b673cf 100644 --- a/include/boost/container/detail/adaptive_node_pool_impl.hpp +++ b/include/boost/container/detail/adaptive_node_pool_impl.hpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -780,7 +781,7 @@ class private_adaptive_node_pool_impl //In case of error, free memory deallocating all nodes (the new ones allocated //in this function plus previously stored nodes in chain). this->deallocate_nodes(chain); - throw std::bad_alloc(); + throw_bad_alloc(); } block_info_t &c_info = *new(mem_address)block_info_t(); mem_address += HdrSize; @@ -812,7 +813,7 @@ class private_adaptive_node_pool_impl //In case of error, free memory deallocating all nodes (the new ones allocated //in this function plus previously stored nodes in chain). this->deallocate_nodes(chain); - throw std::bad_alloc(); + throw_bad_alloc(); } //First initialize header information on the last subblock char *hdr_addr = mem_address + m_real_block_alignment*(m_num_subblocks-1); diff --git a/include/boost/container/detail/allocator_version_traits.hpp b/include/boost/container/detail/allocator_version_traits.hpp index d69e61b..4cef676 100644 --- a/include/boost/container/detail/allocator_version_traits.hpp +++ b/include/boost/container/detail/allocator_version_traits.hpp @@ -18,13 +18,13 @@ #include #include #include //allocator_traits +#include #include //multiallocation_chain #include //version_type #include //allocation_type #include //integral_constant #include //pointer_traits #include //pair -#include //runtime_error #include //BOOST_TRY namespace boost { @@ -135,7 +135,7 @@ struct allocator_version_traits std::pair ret(pointer(), false); if(!(command & allocate_new)){ if(!(command & nothrow_allocation)){ - throw std::runtime_error("version 1 allocator without allocate_new flag"); + throw_logic_error("version 1 allocator without allocate_new flag"); } } else{ diff --git a/include/boost/container/flat_map.hpp b/include/boost/container/flat_map.hpp index 2dd2210..8bb372f 100644 --- a/include/boost/container/flat_map.hpp +++ b/include/boost/container/flat_map.hpp @@ -22,13 +22,14 @@ #include #include #include -#include #include #include #include #include +#include #include #include +#include namespace boost { namespace container { @@ -478,7 +479,7 @@ class flat_map { iterator i = this->find(k); if(i == this->end()){ - throw std::out_of_range("key not found"); + throw_out_of_range("flat_map::at key not found"); } return i->second; } @@ -492,7 +493,7 @@ class flat_map { const_iterator i = this->find(k); if(i == this->end()){ - throw std::out_of_range("key not found"); + throw_out_of_range("flat_map::at key not found"); } return i->second; } diff --git a/include/boost/container/list.hpp b/include/boost/container/list.hpp index 571e63a..79f4a6b 100644 --- a/include/boost/container/list.hpp +++ b/include/boost/container/list.hpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -36,13 +37,11 @@ #include #endif -#include #include #include #include #include #include -#include namespace boost { namespace container { diff --git a/include/boost/container/map.hpp b/include/boost/container/map.hpp index d4ab423..b1faf49 100644 --- a/include/boost/container/map.hpp +++ b/include/boost/container/map.hpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -30,10 +29,12 @@ #include #include #include +#include #include #include #include #include +#include namespace boost { namespace container { @@ -423,7 +424,7 @@ class map { iterator i = this->find(k); if(i == this->end()){ - throw std::out_of_range("key not found"); + throw_out_of_range("map::at key not found"); } return i->second; } @@ -435,7 +436,7 @@ class map { const_iterator i = this->find(k); if(i == this->end()){ - throw std::out_of_range("key not found"); + throw_out_of_range("map::at key not found"); } return i->second; } diff --git a/include/boost/container/slist.hpp b/include/boost/container/slist.hpp index 84cccda..39bf0c2 100644 --- a/include/boost/container/slist.hpp +++ b/include/boost/container/slist.hpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -37,7 +38,6 @@ #include #endif -#include #include #include #include diff --git a/include/boost/container/stable_vector.hpp b/include/boost/container/stable_vector.hpp index 539b2da..759124c 100644 --- a/include/boost/container/stable_vector.hpp +++ b/include/boost/container/stable_vector.hpp @@ -1,4 +1,4 @@ - +////////////////////////////////////////////////////////////////////////////// // // (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file @@ -29,18 +29,21 @@ #include #include #include +#include #include #include #include #include #include +#include #include +#include #include #include #include #include #include //max -#include + #include #include //placement new @@ -1010,8 +1013,9 @@ class stable_vector void reserve(size_type n) { STABLE_VECTOR_CHECK_INVARIANT; - if(n > this->max_size()) - throw std::bad_alloc(); + if(n > this->max_size()){ + throw_length_error("stable_vector::reserve max_size() exceeded"); + } size_type sz = this->size(); size_type old_capacity = this->capacity(); @@ -1143,8 +1147,9 @@ class stable_vector //! Complexity: Constant. reference at(size_type n) { - if(n>=this->size()) - throw std::out_of_range("invalid subscript at stable_vector::at"); + if(n >= this->size()){ + throw_out_of_range("vector::at invalid subscript"); + } return operator[](n); } @@ -1158,8 +1163,9 @@ class stable_vector //! Complexity: Constant. const_reference at(size_type n)const { - if(n>=this->size()) - throw std::out_of_range("invalid subscript at stable_vector::at"); + if(n >= this->size()){ + throw_out_of_range("vector::at invalid subscript"); + } return operator[](n); } diff --git a/include/boost/container/string.hpp b/include/boost/container/string.hpp index 40b2397..74dd051 100644 --- a/include/boost/container/string.hpp +++ b/include/boost/container/string.hpp @@ -38,6 +38,7 @@ #include #include +#include #include #include #include @@ -54,8 +55,7 @@ #include #include -#include -#include +#include #include #include #include @@ -335,8 +335,9 @@ class basic_string_base this->priv_storage(new_cap); } } - else - throw_length_error(); + else{ + throw_length_error("basic_string::allocate_initial_block max_size() exceeded"); + } } void deallocate_block() @@ -345,13 +346,6 @@ class basic_string_base size_type max_size() const { return allocator_traits_type::max_size(this->alloc()) - 1; } - // Helper functions for exception handling. - void throw_length_error() const - { throw(std::length_error("basic_string")); } - - void throw_out_of_range() const - { throw(std::out_of_range("basic_string")); } - protected: size_type priv_capacity() const { return this->priv_storage() - 1; } @@ -663,7 +657,7 @@ class basic_string { this->priv_terminate_string(); if (pos > s.size()) - this->throw_out_of_range(); + throw_out_of_range("basic_string::basic_string out of range position"); else this->assign (s.begin() + pos, s.begin() + pos + container_detail::min_value(n, s.size() - pos)); @@ -991,7 +985,7 @@ class basic_string void reserve(size_type res_arg) { if (res_arg > this->max_size()){ - this->throw_length_error(); + throw_length_error("basic_string::reserve max_size() exceeded"); } if (this->capacity() < res_arg){ @@ -1083,7 +1077,7 @@ class basic_string reference at(size_type n) { if (n >= this->size()) - this->throw_out_of_range(); + throw_out_of_range("basic_string::at invalid subscript"); return *(this->priv_addr() + n); } @@ -1097,7 +1091,7 @@ class basic_string //! Complexity: Constant. const_reference at(size_type n) const { if (n >= this->size()) - this->throw_out_of_range(); + throw_out_of_range("basic_string::at invalid subscript"); return *(this->priv_addr() + n); } @@ -1142,7 +1136,7 @@ class basic_string basic_string& append(const basic_string& s, size_type pos, size_type n) { if (pos > s.size()) - this->throw_out_of_range(); + throw_out_of_range("basic_string::append out of range position"); return this->append(s.begin() + pos, s.begin() + pos + container_detail::min_value(n, s.size() - pos)); } @@ -1226,7 +1220,7 @@ class basic_string basic_string& assign(const basic_string& s, size_type pos, size_type n) { if (pos > s.size()) - this->throw_out_of_range(); + throw_out_of_range("basic_string::assign out of range position"); return this->assign(s.begin() + pos, s.begin() + pos + container_detail::min_value(n, s.size() - pos)); } @@ -1296,9 +1290,9 @@ class basic_string { const size_type sz = this->size(); if (pos > sz) - this->throw_out_of_range(); + throw_out_of_range("basic_string::insert out of range position"); if (sz > this->max_size() - s.size()) - this->throw_length_error(); + throw_length_error("basic_string::insert max_size() exceeded"); this->insert(this->priv_addr() + pos, s.begin(), s.end()); return *this; } @@ -1316,10 +1310,10 @@ class basic_string const size_type sz = this->size(); const size_type str_size = s.size(); if (pos1 > sz || pos2 > str_size) - this->throw_out_of_range(); + throw_out_of_range("basic_string::insert out of range position"); size_type len = container_detail::min_value(n, str_size - pos2); if (sz > this->max_size() - len) - this->throw_length_error(); + throw_length_error("basic_string::insert max_size() exceeded"); const CharT *beg_ptr = container_detail::to_raw_pointer(s.begin()) + pos2; const CharT *end_ptr = beg_ptr + len; this->insert(this->priv_addr() + pos1, beg_ptr, end_ptr); @@ -1340,9 +1334,9 @@ class basic_string basic_string& insert(size_type pos, const CharT* s, size_type n) { if (pos > this->size()) - this->throw_out_of_range(); + throw_out_of_range("basic_string::insert out of range position"); if (this->size() > this->max_size() - n) - this->throw_length_error(); + throw_length_error("basic_string::insert max_size() exceeded"); this->insert(this->priv_addr() + pos, s, s + n); return *this; } @@ -1358,10 +1352,10 @@ class basic_string basic_string& insert(size_type pos, const CharT* s) { if (pos > this->size()) - this->throw_out_of_range(); + throw_out_of_range("basic_string::insert out of range position"); size_type len = Traits::length(s); if (this->size() > this->max_size() - len) - this->throw_length_error(); + throw_length_error("basic_string::insert max_size() exceeded"); this->insert(this->priv_addr() + pos, s, s + len); return *this; } @@ -1375,9 +1369,9 @@ class basic_string basic_string& insert(size_type pos, size_type n, CharT c) { if (pos > this->size()) - this->throw_out_of_range(); + throw_out_of_range("basic_string::insert out of range position"); if (this->size() > this->max_size() - n) - this->throw_length_error(); + throw_length_error("basic_string::insert max_size() exceeded"); this->insert(const_iterator(this->priv_addr() + pos), n, c); return *this; } @@ -1551,7 +1545,7 @@ class basic_string basic_string& erase(size_type pos = 0, size_type n = npos) { if (pos > this->size()) - this->throw_out_of_range(); + throw_out_of_range("basic_string::erase out of range position"); const pointer addr = this->priv_addr(); erase(addr + pos, addr + pos + container_detail::min_value(n, this->size() - pos)); return *this; @@ -1633,10 +1627,10 @@ class basic_string basic_string& replace(size_type pos1, size_type n1, const basic_string& str) { if (pos1 > this->size()) - this->throw_out_of_range(); + throw_out_of_range("basic_string::replace out of range position"); const size_type len = container_detail::min_value(n1, this->size() - pos1); if (this->size() - len >= this->max_size() - str.size()) - this->throw_length_error(); + throw_length_error("basic_string::replace max_size() exceeded"); const pointer addr = this->priv_addr(); return this->replace( const_iterator(addr + pos1) , const_iterator(addr + pos1 + len) @@ -1656,11 +1650,11 @@ class basic_string const basic_string& str, size_type pos2, size_type n2) { if (pos1 > this->size() || pos2 > str.size()) - this->throw_out_of_range(); + throw_out_of_range("basic_string::replace out of range position"); const size_type len1 = container_detail::min_value(n1, this->size() - pos1); const size_type len2 = container_detail::min_value(n2, str.size() - pos2); if (this->size() - len1 >= this->max_size() - len2) - this->throw_length_error(); + throw_length_error("basic_string::replace max_size() exceeded"); const pointer addr = this->priv_addr(); const pointer straddr = str.priv_addr(); return this->replace(addr + pos1, addr + pos1 + len1, @@ -1684,10 +1678,10 @@ class basic_string basic_string& replace(size_type pos1, size_type n1, const CharT* s, size_type n2) { if (pos1 > this->size()) - this->throw_out_of_range(); + throw_out_of_range("basic_string::replace out of range position"); const size_type len = container_detail::min_value(n1, this->size() - pos1); if (n2 > this->max_size() || size() - len >= this->max_size() - n2) - this->throw_length_error(); + throw_length_error("basic_string::replace max_size() exceeded"); const pointer addr = this->priv_addr(); return this->replace(addr + pos1, addr + pos1 + len, s, s + n2); } @@ -1709,11 +1703,11 @@ class basic_string basic_string& replace(size_type pos, size_type n1, const CharT* s) { if (pos > this->size()) - this->throw_out_of_range(); + throw_out_of_range("basic_string::replace out of range position"); const size_type len = container_detail::min_value(n1, this->size() - pos); const size_type n2 = Traits::length(s); if (n2 > this->max_size() || this->size() - len >= this->max_size() - n2) - this->throw_length_error(); + throw_length_error("basic_string::replace max_size() exceeded"); const pointer addr = this->priv_addr(); return this->replace(addr + pos, addr + pos + len, s, s + Traits::length(s)); @@ -1730,10 +1724,10 @@ class basic_string basic_string& replace(size_type pos1, size_type n1, size_type n2, CharT c) { if (pos1 > this->size()) - this->throw_out_of_range(); + throw_out_of_range("basic_string::replace out of range position"); const size_type len = container_detail::min_value(n1, this->size() - pos1); if (n2 > this->max_size() || this->size() - len >= this->max_size() - n2) - this->throw_length_error(); + throw_length_error("basic_string::replace max_size() exceeded"); const pointer addr = this->priv_addr(); return this->replace(addr + pos1, addr + pos1 + len, n2, c); } @@ -1858,7 +1852,7 @@ class basic_string size_type copy(CharT* s, size_type n, size_type pos = 0) const { if (pos > this->size()) - this->throw_out_of_range(); + throw_out_of_range("basic_string::copy out of range position"); const size_type len = container_detail::min_value(n, this->size() - pos); Traits::copy(s, container_detail::to_raw_pointer(this->priv_addr() + pos), len); return len; @@ -2230,7 +2224,7 @@ class basic_string basic_string substr(size_type pos = 0, size_type n = npos) const { if (pos > this->size()) - this->throw_out_of_range(); + throw_out_of_range("basic_string::substr out of range position"); const pointer addr = this->priv_addr(); return basic_string(addr + pos, addr + pos + container_detail::min_value(n, size() - pos), this->alloc()); @@ -2263,7 +2257,7 @@ class basic_string int compare(size_type pos1, size_type n1, const basic_string& str) const { if (pos1 > this->size()) - this->throw_out_of_range(); + throw_out_of_range("basic_string::compare out of range position"); const pointer addr = this->priv_addr(); const pointer str_addr = str.priv_addr(); return s_compare(addr + pos1, @@ -2282,7 +2276,7 @@ class basic_string int compare(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2) const { if (pos1 > this->size() || pos2 > str.size()) - this->throw_out_of_range(); + throw_out_of_range("basic_string::compare out of range position"); const pointer addr = this->priv_addr(); const pointer str_addr = str.priv_addr(); return s_compare(addr + pos1, @@ -2309,7 +2303,7 @@ class basic_string int compare(size_type pos1, size_type n1, const CharT* s, size_type n2) const { if (pos1 > this->size()) - this->throw_out_of_range(); + throw_out_of_range("basic_string::compare out of range position"); const pointer addr = this->priv_addr(); return s_compare( addr + pos1, addr + pos1 + container_detail::min_value(n1, this->size() - pos1), diff --git a/include/boost/container/throw_exception.hpp b/include/boost/container/throw_exception.hpp new file mode 100644 index 0000000..e22d104 --- /dev/null +++ b/include/boost/container/throw_exception.hpp @@ -0,0 +1,110 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2012-2013. 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) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_CONTAINER_THROW_EXCEPTION_HPP +#define BOOST_CONTAINER_THROW_EXCEPTION_HPP + +#include +#include + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#ifndef BOOST_NO_EXCEPTIONS + #include //for std exception types + #include //for std::bad_alloc +#else + #include + #include //for std::abort +#endif + +namespace boost { +namespace container { + +#if defined(BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS) + //The user must provide definitions for the following functions + + void throw_bad_alloc(); + + void throw_out_of_range(const char* str); + + void throw_length_error(const char* str); + + void throw_logic_error(const char* str); + + void throw_runtime_error(const char* str); + +#elif defined(BOOST_NO_EXCEPTIONS) + + inline void throw_bad_alloc() + { + BOOST_ASSERT(!"boost::container bad_alloc thrown"); + std::abort(); + } + + inline void throw_out_of_range(const char* str) + { + BOOST_ASSERT_MSG(!"boost::container out_of_range thrown", str); + std::abort(); + } + + inline void throw_length_error(const char* str) + { + BOOST_ASSERT_MSG(!"boost::container length_error thrown", str); + std::abort(); + } + + inline void throw_logic_error(const char* str) + { + BOOST_ASSERT_MSG(!"boost::container logic_error thrown", str); + std::abort(); + } + + inline void throw_runtime_error(const char* str) + { + BOOST_ASSERT_MSG(!"boost::container runtime_error thrown", str); + std::abort(); + } + +#else //defined(BOOST_NO_EXCEPTIONS) + + inline void throw_bad_alloc() + { + throw std::bad_alloc(); + } + + inline void throw_out_of_range(const char* str) + { + throw std::out_of_range(str); + } + + inline void throw_length_error(const char* str) + { + throw std::length_error(str); + } + + inline void throw_logic_error(const char* str) + { + throw std::logic_error(str); + } + + inline void throw_runtime_error(const char* str) + { + throw std::runtime_error(str); + } + +#endif + +}} //namespace boost { namespace container { + +#include + +#endif //#ifndef BOOST_CONTAINER_THROW_EXCEPTION_HPP diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp index 3c4c9c5..2712cac 100644 --- a/include/boost/container/vector.hpp +++ b/include/boost/container/vector.hpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -41,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -2038,8 +2038,9 @@ class vector : private container_detail::vector_alloc_holder void priv_check_range(size_type n) const { //If n is out of range, throw an out_of_range exception - if (n >= this->size()) - throw std::out_of_range("vector::at"); + if (n >= this->size()){ + throw_out_of_range("vector::at out of range"); + } } #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS diff --git a/proj/vc7ide/container.sln b/proj/vc7ide/container.sln index 68beb93..584f8ab 100644 --- a/proj/vc7ide/container.sln +++ b/proj/vc7ide/container.sln @@ -55,6 +55,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hash_table_test", "hash_tab ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "throw_exception_test", "throw_exception_test.vcproj", "{5A8D91E0-FA57-284F-84FE-D3A6BA792002}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject Global GlobalSection(SolutionConfiguration) = preSolution Debug = Debug @@ -119,6 +123,10 @@ Global {58CCE183-6092-48FE-A4F7-BA0D3A792606}.Debug.Build.0 = Debug|Win32 {58CCE183-6092-48FE-A4F7-BA0D3A792606}.Release.ActiveCfg = Release|Win32 {58CCE183-6092-48FE-A4F7-BA0D3A792606}.Release.Build.0 = Release|Win32 + {5A8D91E0-FA57-284F-84FE-D3A6BA792002}.Debug.ActiveCfg = Debug|Win32 + {5A8D91E0-FA57-284F-84FE-D3A6BA792002}.Debug.Build.0 = Debug|Win32 + {5A8D91E0-FA57-284F-84FE-D3A6BA792002}.Release.ActiveCfg = Release|Win32 + {5A8D91E0-FA57-284F-84FE-D3A6BA792002}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection diff --git a/proj/vc7ide/container.vcproj b/proj/vc7ide/container.vcproj index 5c89b16..5deba8d 100644 --- a/proj/vc7ide/container.vcproj +++ b/proj/vc7ide/container.vcproj @@ -185,6 +185,9 @@ + + @@ -221,6 +224,9 @@ + + @@ -260,6 +266,9 @@ + + diff --git a/proj/vc7ide/throw_exception_test.vcproj b/proj/vc7ide/throw_exception_test.vcproj new file mode 100644 index 0000000..12b7bb8 --- /dev/null +++ b/proj/vc7ide/throw_exception_test.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/vector_test.vcproj b/proj/vc7ide/vector_test.vcproj index 270f5cf..1076c97 100644 --- a/proj/vc7ide/vector_test.vcproj +++ b/proj/vc7ide/vector_test.vcproj @@ -22,6 +22,7 @@ AdditionalIncludeDirectories="../../../.." PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB" MinimalRebuild="TRUE" + ExceptionHandling="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="3" TreatWChar_tAsBuiltInType="TRUE" diff --git a/test/deque_test.cpp b/test/deque_test.cpp index 23a8e58..0ca9fef 100644 --- a/test/deque_test.cpp +++ b/test/deque_test.cpp @@ -29,6 +29,7 @@ #include "emplace_test.hpp" #include "propagate_allocator_test.hpp" #include "vector_test.hpp" +#include using namespace boost::container; @@ -143,7 +144,7 @@ bool do_test() typedef deque MyCntDeque; typedef std::deque MyStdDeque; const int max = 100; - try{ + BOOST_TRY{ //Shared memory allocator must be always be initialized //since it has no default constructor MyCntDeque *cntdeque = new MyCntDeque; @@ -268,10 +269,13 @@ bool do_test() delete cntdeque; delete stddeque; } - catch(std::exception &ex){ + BOOST_CATCH(std::exception &ex){ + #ifndef BOOST_NO_EXCEPTIONS std::cout << ex.what() << std::endl; + #endif return false; } + BOOST_CATCH_END std::cout << std::endl << "Test OK!" << std::endl; return true; diff --git a/test/dummy_test_allocator.hpp b/test/dummy_test_allocator.hpp index ef95836..993cccf 100644 --- a/test/dummy_test_allocator.hpp +++ b/test/dummy_test_allocator.hpp @@ -26,11 +26,11 @@ #include #include #include +#include #include #include #include #include -#include #include //!\file diff --git a/test/expand_bwd_test_allocator.hpp b/test/expand_bwd_test_allocator.hpp index a39aaf1..882552a 100644 --- a/test/expand_bwd_test_allocator.hpp +++ b/test/expand_bwd_test_allocator.hpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -26,7 +27,6 @@ #include #include #include -#include #include //!\file @@ -146,8 +146,8 @@ class expand_bwd_test_allocator return std::pair(mp_buffer, true); } else{ - assert(0); - throw std::bad_alloc(); + throw_bad_alloc(); + return std::pair(mp_buffer, true); } } diff --git a/test/expand_bwd_test_template.hpp b/test/expand_bwd_test_template.hpp index 0f06e23..c1f26e1 100644 --- a/test/expand_bwd_test_template.hpp +++ b/test/expand_bwd_test_template.hpp @@ -135,7 +135,7 @@ bool test_insert_with_expand_bwd() for(int iteration = 0; iteration < Iterations; ++iteration) { value_type *memory = new value_type[MemorySize]; - try { + BOOST_TRY { std::vector initial_data; initial_data.resize(InitialSize[iteration]); for(int i = 0; i < InitialSize[iteration]; ++i){ @@ -165,10 +165,11 @@ bool test_insert_with_expand_bwd() return false; } } - catch(...){ + BOOST_CATCH(...){ delete [](const_cast(memory)); - throw; + BOOST_RETHROW; } + BOOST_CATCH_END delete [](const_cast(memory)); } @@ -193,7 +194,7 @@ bool test_assign_with_expand_bwd() for(int iteration = 0; iteration initial_data; initial_data.resize(InitialSize[iteration]); @@ -227,10 +228,11 @@ bool test_assign_with_expand_bwd() return false; } } - catch(...){ + BOOST_CATCH(...){ delete [](const_cast::type*>(memory)); - throw; + BOOST_RETHROW; } + BOOST_CATCH_END delete [](const_cast::type*>(memory)); } diff --git a/test/heap_allocator_v1.hpp b/test/heap_allocator_v1.hpp index 56fc1a2..b7724d2 100644 --- a/test/heap_allocator_v1.hpp +++ b/test/heap_allocator_v1.hpp @@ -28,7 +28,6 @@ #include #include #include -#include //!\file //!Describes an heap_allocator_v1 that allocates portions of fixed size diff --git a/test/list_test.hpp b/test/list_test.hpp index e1f0ec6..0ce580b 100644 --- a/test/list_test.hpp +++ b/test/list_test.hpp @@ -148,7 +148,7 @@ int list_test (bool copied_allocators_equal = true) const int max = 100; typedef list_push_data_function push_data_t; - try{ + BOOST_TRY{ MyBoostList *boostlist = new MyBoostList; MyStdList *stdlist = new MyStdList; @@ -338,9 +338,10 @@ int list_test (bool copied_allocators_equal = true) delete boostlist; delete stdlist; } - catch(...){ - throw; + BOOST_CATCH(...){ + BOOST_RETHROW; } + BOOST_CATCH_END return 0; } diff --git a/test/map_test.hpp b/test/map_test.hpp index 96ea05d..2357f57 100644 --- a/test/map_test.hpp +++ b/test/map_test.hpp @@ -44,7 +44,7 @@ int map_test () typedef typename MyStdMap::value_type StdPairType; const int max = 100; - try{ + BOOST_TRY{ MyBoostMap *boostmap = new MyBoostMap; MyStdMap *stdmap = new MyStdMap; MyBoostMultiMap *boostmultimap = new MyBoostMultiMap; @@ -467,9 +467,10 @@ int map_test () delete boostmultimap; delete stdmultimap; } - catch(...){ - throw; + BOOST_CATCH(...){ + BOOST_RETHROW; } + BOOST_CATCH_END return 0; } @@ -485,7 +486,7 @@ int map_test_copyable () const int max = 100; - try{ + BOOST_TRY{ MyBoostMap *boostmap = new MyBoostMap; MyStdMap *stdmap = new MyStdMap; MyBoostMultiMap *boostmultimap = new MyBoostMultiMap; @@ -537,9 +538,10 @@ int map_test_copyable () delete stdmultimap; } } - catch(...){ - throw; + BOOST_CATCH(...){ + BOOST_RETHROW; } + BOOST_CATCH_END return 0; } diff --git a/test/set_test.hpp b/test/set_test.hpp index 91397c9..7a2b844 100644 --- a/test/set_test.hpp +++ b/test/set_test.hpp @@ -443,7 +443,7 @@ int set_test_copyable () typedef typename MyBoostSet::value_type IntType; const int max = 100; - try{ + BOOST_TRY{ //Shared memory allocator must be always be initialized //since it has no default constructor MyBoostSet *boostset = new MyBoostSet; @@ -492,9 +492,10 @@ int set_test_copyable () delete boostset; delete boostmultiset; } - catch(...){ - throw; + BOOST_CATCH(...){ + BOOST_RETHROW; } + BOOST_CATCH_END return 0; } diff --git a/test/throw_exception_test.cpp b/test/throw_exception_test.cpp new file mode 100644 index 0000000..2572dfe --- /dev/null +++ b/test/throw_exception_test.cpp @@ -0,0 +1,62 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2012-2013. 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) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#define BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS + +#include + +#include +#include + +using namespace boost::container; + +static bool bad_alloc_called = false; +static bool out_of_range_called = false; +static bool length_error_called = false; +static bool logic_error_called = false; +static bool runtime_error_called = false; + +//User defined throw implementations +namespace boost { +namespace container { + + void throw_bad_alloc() + { bad_alloc_called = true; } + + void throw_out_of_range(const char* str) + { (void)str; out_of_range_called = true; } + + void throw_length_error(const char* str) + { (void)str; length_error_called = true; } + + void throw_logic_error(const char* str) + { (void)str; logic_error_called = true; } + + void throw_runtime_error(const char* str) + { (void)str; runtime_error_called = true; } + +}} //boost::container + +int main() +{ + //Check user-defined throw callbacks are called + throw_bad_alloc(); + BOOST_TEST(bad_alloc_called == true); + throw_out_of_range("dummy"); + BOOST_TEST(out_of_range_called == true); + throw_length_error("dummy"); + BOOST_TEST(length_error_called == true); + throw_logic_error("dummy"); + BOOST_TEST(logic_error_called == true); + throw_runtime_error("dummy"); + BOOST_TEST(runtime_error_called == true); + return ::boost::report_errors(); +} + +#include diff --git a/test/vector_test.hpp b/test/vector_test.hpp index 503ec59..318e339 100644 --- a/test/vector_test.hpp +++ b/test/vector_test.hpp @@ -30,6 +30,7 @@ #include "input_from_forward_iterator.hpp" #include #include +#include namespace boost{ namespace container { @@ -91,7 +92,7 @@ int vector_test() const int max = 100; { - try{ + BOOST_TRY{ MyBoostVector *boostvector = new MyBoostVector; MyStdVector *stdvector = new MyStdVector; boostvector->resize(100); @@ -292,10 +293,13 @@ int vector_test() delete stdvector; delete boostvector; } - catch(std::exception &ex){ + BOOST_CATCH(std::exception &ex){ + #ifndef BOOST_NO_EXCEPTIONS std::cout << ex.what() << std::endl; + #endif return 1; } + BOOST_CATCH_END } std::cout << std::endl << "Test OK!" << std::endl; return 0;