diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c481245..d86a1dda 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -161,7 +161,7 @@ list ( alloc/raw/affix.hpp alloc/raw/aligned/direct.hpp alloc/raw/aligned/foreign.hpp - alloc/raw/dynamic.hpp + #alloc/raw/dynamic.hpp alloc/raw/fallback.cpp alloc/raw/fallback.hpp alloc/raw/linear.cpp @@ -478,7 +478,7 @@ if (TESTS) alloc/aligned/foreign alloc/aligned/direct alloc/arena - alloc/dynamic + #alloc/dynamic alloc/linear alloc/stack alloc/forwarding diff --git a/alloc/arena.hpp b/alloc/arena.hpp index 0a69c4e4..6e805fc0 100644 --- a/alloc/arena.hpp +++ b/alloc/arena.hpp @@ -19,6 +19,7 @@ #include "../memory/deleter.hpp" #include "../cast.hpp" +#include "../view.hpp" #include #include @@ -38,14 +39,12 @@ namespace util::alloc { U* acquire (Args&&... args) { - U *data = util::cast::alignment ( - m_store.allocate (sizeof (U), alignof (U)).data () - ); + U *data = m_store.template allocate (1).data (); try { new (data) U (std::forward (args)...); } catch (...) { - m_store.deallocate (data, sizeof (U)); + m_store.template deallocate ({data,1}); throw; } @@ -58,7 +57,7 @@ namespace util::alloc { release (U *u) { u->~U (); - m_store.deallocate (reinterpret_cast (u), sizeof (U)); + m_store.template deallocate (util::view {u,1u}); } diff --git a/alloc/forwarding.hpp b/alloc/forwarding.hpp index 39db3bea..6c042cd4 100644 --- a/alloc/forwarding.hpp +++ b/alloc/forwarding.hpp @@ -27,16 +27,16 @@ namespace util::alloc { m_backing (backing) { ; } - template + template auto allocate (Args &&...args) { - return m_backing.allocate (std::forward (args)...); + return m_backing.template allocate (std::forward (args)...); } - template + template auto deallocate (Args &&...args) { - return m_backing.deallocate (std::forward (args)...); + return m_backing.template deallocate (std::forward (args)...); } auto data (void) { return m_backing.data (); } diff --git a/alloc/raw/affix.hpp b/alloc/raw/affix.hpp index 2ec10fd9..efd5699e 100644 --- a/alloc/raw/affix.hpp +++ b/alloc/raw/affix.hpp @@ -31,13 +31,15 @@ namespace util::alloc::raw { /// useful for sentinels, reference counts, etc. template class affix { - util::view allocate (size_t bytes); - util::view allocate (size_t bytes, size_t align); - void deallocate (util::view ptr) { return deallocate (ptr.data (), ptr.size ()); } - void deallocate (util::view ptr, size_t alignment) { return deallocate (ptr.data (), ptr.size (), alignment); } - void deallocate (void *ptr, size_t bytes); - void deallocate (void *ptr, size_t bytes, size_t align); + template + util::view allocate (size_t bytes); + + template + util::view allocate (size_t bytes, size_t align); + + template + void deallocate (util::view); std::byte* begin (void); const std::byte* begin (void) const; diff --git a/alloc/raw/aligned/direct.hpp b/alloc/raw/aligned/direct.hpp index de00d653..ec46e039 100644 --- a/alloc/raw/aligned/direct.hpp +++ b/alloc/raw/aligned/direct.hpp @@ -37,17 +37,19 @@ namespace util::alloc::raw::aligned { /////////////////////////////////////////////////////////////////////// + template auto - allocate (std::size_t bytes) + allocate (std::size_t count) { - return m_successor.allocate (bytes, m_alignment); + return m_successor.template allocate (count, m_alignment); } //--------------------------------------------------------------------- + template auto - deallocate (void *ptr, std::size_t bytes) + deallocate (util::view ptr) { - return m_successor.deallocate (ptr, bytes); + return m_successor.template deallocate (ptr); } diff --git a/alloc/raw/aligned/foreign.hpp b/alloc/raw/aligned/foreign.hpp index 3313211b..5c6ca898 100644 --- a/alloc/raw/aligned/foreign.hpp +++ b/alloc/raw/aligned/foreign.hpp @@ -19,6 +19,7 @@ #include "direct.hpp" +#include "../../../cast.hpp" #include "../../../pointer.hpp" #include "../../../debug.hpp" @@ -66,20 +67,29 @@ namespace util::alloc::raw::aligned { { ; } - void* - allocate (std::size_t size) + template + util::view + allocate (std::size_t count) { - auto ptr= reinterpret_cast ( - m_successor.allocate (size).data () - ); - return ptr + m_offset; + auto root = m_successor.template allocate (count); + auto base = root.template cast ().data (); + + // we can't use alignment cast here because it will almost + // certainly fail the tests it performs. + return { util::cast::ffs (base + m_offset), count }; } + template auto - deallocate (void *ptr, std::size_t size) + deallocate (util::view ptr) { - return m_successor.deallocate ( - reinterpret_cast (ptr) - m_offset, size + auto base = ptr.template cast (); + auto next = base - m_offset; + + // we can't use alignment cast here because it will almost + // certainly fail the tests it performs. + return m_successor.template deallocate ( + util::view { util::cast::ffs (next), ptr.size () } ); } diff --git a/alloc/raw/dynamic.hpp b/alloc/raw/dynamic.hpp index fa9a294c..9dd94b96 100644 --- a/alloc/raw/dynamic.hpp +++ b/alloc/raw/dynamic.hpp @@ -58,8 +58,11 @@ namespace util::alloc::raw { // dynamically eliminate the function altogether given run-time // dynamic dispatch needs the common calls exposed to the clients, and // aligned allocate is stupid useful. - auto allocate (size_t bytes) { return m_child->allocate (bytes); } - auto allocate (size_t bytes, size_t alignment) { return m_child->allocate (bytes, alignment); } + template + auto allocate (size_t bytes) { return m_child->allocate (bytes); } + + template + auto allocate (size_t bytes, size_t alignment) { return m_child->allocate (bytes, alignment); } auto deallocate (void *ptr, size_t bytes) { return m_child->deallocate (ptr, bytes); } diff --git a/alloc/raw/fallback.hpp b/alloc/raw/fallback.hpp index ce2b880d..f4e791a9 100644 --- a/alloc/raw/fallback.hpp +++ b/alloc/raw/fallback.hpp @@ -32,13 +32,16 @@ namespace util::alloc::raw { m_children (_children...) { ; } - util::view allocate (size_t bytes); - util::view allocate (size_t bytes, size_t align); + template + util::view + allocate (size_t bytes); - void deallocate (util::view ptr) { return deallocate (ptr.data (), ptr.size ()); } - void deallocate (util::view ptr, size_t alignment) { return deallocate (ptr.data (), ptr.size (), alignment); } - void deallocate (void *ptr, size_t bytes); - void deallocate (void *ptr, size_t bytes, size_t align); + template + util::view + allocate (size_t bytes, size_t align); + + template + void deallocate (util::view ptr); private: std::tuple m_children; diff --git a/alloc/raw/linear.cpp b/alloc/raw/linear.cpp index c34a5a06..013650c3 100644 --- a/alloc/raw/linear.cpp +++ b/alloc/raw/linear.cpp @@ -31,51 +31,6 @@ linear::linear (util::view _data): /////////////////////////////////////////////////////////////////////////////// -util::view -linear::allocate (size_t bytes) -{ - if (m_cursor + bytes > m_end) - throw std::bad_alloc (); - - auto ptr = m_cursor; - m_cursor += bytes; - return { ptr, bytes }; -} - - -//----------------------------------------------------------------------------- -util::view -linear::allocate (size_t bytes, size_t alignment) -{ - auto ptr = align (m_cursor, alignment); - if (ptr + bytes > m_end) - throw std::bad_alloc (); - - m_cursor = ptr + bytes; - - return { ptr, bytes }; -} - - -//----------------------------------------------------------------------------- -void -linear::deallocate (void *ptr, size_t bytes) -{ - deallocate (ptr, bytes, alignof (std::max_align_t)); -} - - -//----------------------------------------------------------------------------- -void -linear::deallocate (void *ptr, size_t bytes, size_t alignment) -{ - (void)ptr; - (void)bytes; - (void)alignment; -} - - -//----------------------------------------------------------------------------- std::byte* linear::data (void) { diff --git a/alloc/raw/linear.hpp b/alloc/raw/linear.hpp index c217584c..5d73cb96 100644 --- a/alloc/raw/linear.hpp +++ b/alloc/raw/linear.hpp @@ -18,6 +18,7 @@ #define CRUFT_UTIL_ALLOC_RAW_LINEAR_HPP #include "../../view.hpp" +#include "../../pointer.hpp" #include #include @@ -34,13 +35,40 @@ namespace util::alloc::raw { linear (util::view _data); - util::view allocate (size_t bytes); - util::view allocate (size_t bytes, size_t alignment); + template + util::view + allocate (size_t count) + { + auto const bytes = count * sizeof (T); + if (m_cursor + bytes > m_end) + throw std::bad_alloc (); - void deallocate (util::view ptr) { return deallocate (ptr.data (), ptr.size ()); } - void deallocate (util::view ptr, size_t alignment) { return deallocate (ptr.data (), ptr.size (), alignment); } - void deallocate (void *ptr, size_t bytes); - void deallocate (void *ptr, size_t bytes, size_t alignment); + auto ptr = m_cursor; + m_cursor += bytes; + return { util::cast::alignment (ptr), count }; + } + + + template + util::view + allocate (size_t count, size_t alignment) + { + auto const bytes = count * sizeof (T); + + auto ptr = util::align (m_cursor, alignment); + if (ptr + bytes > m_end) + throw std::bad_alloc (); + + m_cursor = ptr + bytes; + + return { util::cast::alignment (ptr), count }; + } + + template + void deallocate (util::view ptr) + { + (void)ptr; + } std::byte* data (void); std::byte* begin (void); diff --git a/alloc/raw/malloc.cpp b/alloc/raw/malloc.cpp index a7b03c09..333a668e 100644 --- a/alloc/raw/malloc.cpp +++ b/alloc/raw/malloc.cpp @@ -11,7 +11,7 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * Copyright 2015 Danny Robson + * Copyright 2018 Danny Robson */ #include "malloc.hpp" @@ -20,43 +20,3 @@ #include -using util::alloc::raw::malloc; - - -/////////////////////////////////////////////////////////////////////////////// -util::view -malloc::allocate (size_t bytes) -{ - return allocate (bytes, alignof (std::max_align_t)); -} - - -//----------------------------------------------------------------------------- -util::view -malloc::allocate (size_t bytes, size_t align) -{ - // C malloc guarantees maximal alignment - CHECK_LE (align, alignof (std::max_align_t)); - (void)align; - - return util::view (reinterpret_cast (::malloc (bytes)), bytes); -} - - -//----------------------------------------------------------------------------- -void -malloc::deallocate (void *ptr, size_t bytes) -{ - return deallocate (ptr, bytes, alignof (std::max_align_t)); -} - - -//----------------------------------------------------------------------------- -void -malloc::deallocate (void *ptr, size_t bytes, size_t align) -{ - (void)bytes; - (void)align; - - ::free (ptr); -} diff --git a/alloc/raw/malloc.hpp b/alloc/raw/malloc.hpp index dedb3027..1a5fff3d 100644 --- a/alloc/raw/malloc.hpp +++ b/alloc/raw/malloc.hpp @@ -11,7 +11,7 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * Copyright 2015 Danny Robson + * Copyright 2018 Danny Robson */ #ifndef CRUFT_UTIL_ALLOC_RAW_MALLOC_HPP @@ -25,13 +25,33 @@ namespace util::alloc::raw { class malloc { public: - util::view allocate (size_t bytes); - util::view allocate (size_t bytes, size_t align); + template + util::view allocate (size_t count) + { + return { + reinterpret_cast (malloc (sizeof (T) * count)), + count + }; + } - void deallocate (util::view ptr) { return deallocate (ptr.data (), ptr.size ()); } - void deallocate (util::view ptr, size_t alignment) { return deallocate (ptr.data (), ptr.size (), alignment); } - void deallocate (void *ptr, size_t bytes); - void deallocate (void *ptr, size_t bytes, size_t align); + template + util::view + allocate (size_t count, size_t align) + { + void* ptr; + posix_memalign (&ptr, align, sizeof (T) * count); + if (!ptr) + throw std::bad_alloc (); + + return { reinterpret_cast (ptr), count }; + } + + template + void + deallocate (util::view ptr) + { + ::free (ptr.data ()); + } }; } diff --git a/alloc/raw/null.cpp b/alloc/raw/null.cpp index a06359cb..aba5aed3 100644 --- a/alloc/raw/null.cpp +++ b/alloc/raw/null.cpp @@ -24,48 +24,6 @@ using util::alloc::raw::null; -/////////////////////////////////////////////////////////////////////////////// -util::view -null::allocate (size_t bytes) -{ - return allocate (bytes, alignof (std::max_align_t)); -} - - -//----------------------------------------------------------------------------- -util::view -null::allocate (size_t bytes, size_t align) -{ - (void)bytes; - (void)align; - - throw std::bad_alloc (); -} - - -//----------------------------------------------------------------------------- -void -null::deallocate (void *ptr, size_t bytes) -{ - return deallocate (ptr, bytes, alignof (std::max_align_t)); -} - - -//----------------------------------------------------------------------------- -// calling deallocate with a non-null pointer is undefined, but we may as well -// let the application continuing running if we're not in a debug context. -void -null::deallocate (void *ptr, size_t bytes, size_t align) -{ - (void)ptr; - (void)bytes; - (void)align; - - // cast to void* to assist some of the printing machinery in the assertion - CHECK_EQ (ptr, static_cast (nullptr)); -} - - /////////////////////////////////////////////////////////////////////////////// std::byte* null::begin (void) diff --git a/alloc/raw/null.hpp b/alloc/raw/null.hpp index f9e4a8e6..cbbbdba2 100644 --- a/alloc/raw/null.hpp +++ b/alloc/raw/null.hpp @@ -32,13 +32,30 @@ namespace util::alloc::raw { null (const null&) = delete; null& operator= (const null&) = delete; - util::view allocate (size_t bytes); - util::view allocate (size_t bytes, size_t align); + template + util::view + allocate (size_t count) + { + return allocate (count, alignof (T)); + } - void deallocate (util::view ptr) { return deallocate (ptr.data (), ptr.size ()); } - void deallocate (util::view ptr, size_t alignment) { return deallocate (ptr.data (), ptr.size (), alignment); } - void deallocate (void *ptr, size_t bytes); - void deallocate (void *ptr, size_t bytes, size_t align); + template + util::view + allocate (size_t count, size_t align) + { + (void)count; + (void)align; + + throw std::bad_alloc (); + } + + template + void + deallocate (util::view ptr) + { + (void)ptr; + CHECK_EQ (ptr.data (), static_cast (nullptr)); + } util::view data (void); util::view data (void) const; diff --git a/alloc/raw/stack.cpp b/alloc/raw/stack.cpp index 8f363ec7..95dfd338 100644 --- a/alloc/raw/stack.cpp +++ b/alloc/raw/stack.cpp @@ -33,86 +33,6 @@ stack::stack (util::view _data): } -/////////////////////////////////////////////////////////////////////////////// -union record { - using offset_t = uint32_t; - - std::byte *as_bytes; - offset_t *as_offset; -}; - - -//----------------------------------------------------------------------------- -constexpr auto MIN_ALIGNMENT = sizeof (record::offset_t); - - -/////////////////////////////////////////////////////////////////////////////// -util::view -stack::allocate (size_t bytes) -{ - return allocate (bytes, alignof (std::max_align_t)); -} - - -//----------------------------------------------------------------------------- -util::view -stack::allocate (size_t bytes, size_t alignment) -{ - // reserve space at the front of the allocation to record the total - // allocation size so we can account for alignment if required. - auto ptr = m_cursor + sizeof (record::offset_t); - - // align the outgoing pointer if required - alignment = util::max (MIN_ALIGNMENT, alignment); - ptr = align (ptr, alignment); - - // ensure we haven't overrun our allocated segment - if (ptr + bytes > m_end) - throw std::bad_alloc (); - - // use a 'record' struct as a window into the reserved space at the front - // of the allocation and store the offset to the previous allocation head - // (from the record struct). allows us to account for alignment. - record record; - record.as_bytes = ptr - sizeof (record::offset_t); - *record.as_offset = util::cast::lossless (ptr - m_cursor); - - m_cursor = ptr + bytes; - return { ptr, bytes }; -} - - -//----------------------------------------------------------------------------- -void -stack::deallocate (void *ptr, size_t bytes) -{ - return deallocate (ptr, bytes, alignof (std::max_align_t)); -} - - -//----------------------------------------------------------------------------- -void -stack::deallocate (void *_ptr, size_t bytes, size_t alignment) -{ - (void)bytes; - - // TODO: use alignment - (void)alignment; - //alignment = util::max (MIN_ALIGNMENT, alignment); - - auto ptr = reinterpret_cast (_ptr); - - record record; - record.as_bytes = ptr - sizeof (record::offset_t); - - //CHECK_LE (bytes, *record.as_offset); - CHECK_GE (m_cursor - *record.as_offset, m_begin); - - m_cursor -= bytes; - m_cursor -= *record.as_offset; -} - - //----------------------------------------------------------------------------- std::byte* stack::begin (void) diff --git a/alloc/raw/stack.hpp b/alloc/raw/stack.hpp index 8921e073..ad18609c 100644 --- a/alloc/raw/stack.hpp +++ b/alloc/raw/stack.hpp @@ -18,6 +18,7 @@ #define CRUFT_UTIL_ALLOC_RAW_STACK_HPP #include "../../view.hpp" +#include "../../pointer.hpp" #include @@ -34,13 +35,60 @@ namespace util::alloc::raw { stack (util::view _data); - util::view allocate (size_t bytes, size_t alignment); - util::view allocate (size_t bytes); + template + util::view + allocate (size_t count, size_t alignment) + { + constexpr auto MIN_ALIGNMENT = sizeof (record::offset_t); + const auto bytes = count * sizeof (T); + + // reserve space at the front of the allocation to record the total + // allocation size so we can account for alignment if required. + auto ptr = m_cursor + sizeof (record::offset_t); + + // align the outgoing pointer if required + alignment = util::max (MIN_ALIGNMENT, alignment); + ptr = util::align (ptr, alignment); + + // ensure we haven't overrun our allocated segment + if (ptr + bytes > m_end) + throw std::bad_alloc (); + + // use a 'record' struct as a window into the reserved space at the front + // of the allocation and store the offset to the previous allocation head + // (from the record struct). allows us to account for alignment. + record r; + r.as_bytes = ptr - sizeof (record::offset_t); + *r.as_offset = util::cast::lossless (ptr - m_cursor); + + m_cursor = ptr + bytes; + return { util::cast::alignment (ptr), count }; + } + + + template + util::view + allocate (size_t count) + { + return allocate (count, alignof (T)); + } + + + template + void deallocate (util::view _ptr) + { + auto ptr = reinterpret_cast (_ptr.data ()); + + record r; + r.as_bytes = ptr - sizeof (record::offset_t); + + //CHECK_LE (bytes, *record.as_offset); + CHECK_GE (m_cursor - *r.as_offset, m_begin); + + m_cursor -= sizeof (T) * _ptr.size (); + m_cursor -= *r.as_offset; + } - void deallocate (util::view ptr) { return deallocate (ptr.data (), ptr.size ()); } - void deallocate (util::view ptr, size_t alignment) { return deallocate (ptr.data (), ptr.size (), alignment); } - void deallocate (void *ptr, size_t bytes); - void deallocate (void *ptr, size_t bytes, size_t alignment); util::view data (void); util::view data (void) const; @@ -60,6 +108,13 @@ namespace util::alloc::raw { size_t remain (void) const; private: + union record { + using offset_t = uint32_t; + + std::byte *as_bytes; + offset_t *as_offset; + }; + std::byte *const m_begin; std::byte *const m_end; std::byte *m_cursor; diff --git a/test/alloc/aligned/direct.cpp b/test/alloc/aligned/direct.cpp index d801b2ae..51c6ff13 100644 --- a/test/alloc/aligned/direct.cpp +++ b/test/alloc/aligned/direct.cpp @@ -29,10 +29,10 @@ main (int, char**) // alignment to produce a likely system alignment. eg, 3 + 5 == 8 which is // a power-of-2. uintptr_t result[4] = { - reinterpret_cast(alloc.allocate (9).data ()), // just over a power of two - reinterpret_cast(alloc.allocate (1).data ()), // a single byte - reinterpret_cast(alloc.allocate (64).data ()), // a cache line - reinterpret_cast(alloc.allocate (250).data ()) // multiple cache lines, but not a power of two + reinterpret_cast(alloc.allocate (9).data ()), // just over a power of two + reinterpret_cast(alloc.allocate (1).data ()), // a single byte + reinterpret_cast(alloc.allocate (64).data ()), // a cache line + reinterpret_cast(alloc.allocate (250).data ()) // multiple lines, but not a power of two }; tap.expect ( diff --git a/test/alloc/aligned/foreign.cpp b/test/alloc/aligned/foreign.cpp index 16001f32..c7698707 100644 --- a/test/alloc/aligned/foreign.cpp +++ b/test/alloc/aligned/foreign.cpp @@ -27,7 +27,7 @@ main () // ensure the first element allocated falls at the base address tap.expect_eq (base, alloc.data (), "allocator base address is the supplied base address"); - tap.expect_eq (base, alloc.allocate (8), "first allocation is the supplied base address"); + tap.expect_eq (base, alloc.allocate (8).data (), "first allocation is the supplied base address"); // allocate a range of values and make sure they all satisfy our alignment. // don't choose values which are likely to combine with the testing @@ -45,7 +45,7 @@ main () }; for (const auto &t: TESTS) { - auto ptr = reinterpret_cast (alloc.allocate (t.size)); + auto ptr = reinterpret_cast (alloc.allocate (t.size).data ()); auto offset = ptr - reinterpret_cast (base); tap.expect_mod (offset, alignment, "%s", t.message); } diff --git a/test/alloc/forwarding.cpp b/test/alloc/forwarding.cpp index 856794b8..1241b1e1 100644 --- a/test/alloc/forwarding.cpp +++ b/test/alloc/forwarding.cpp @@ -13,7 +13,7 @@ main () util::TAP::logger tap; tap.expect_eq (linear.used (), 0u, "construction does not allocate"); - forwarding.allocate (16u); + forwarding.allocate (16u); tap.expect_eq (linear.used (), 16u, "allocation size is exactly committed"); return tap.status (); diff --git a/test/alloc/linear.cpp b/test/alloc/linear.cpp index 6c71dba5..f9eec950 100644 --- a/test/alloc/linear.cpp +++ b/test/alloc/linear.cpp @@ -18,12 +18,12 @@ main (void) tap.expect_eq (store.capacity (), BUFFER_SIZE, "bytes capacity matches"); tap.expect_throw ( - [&] (void) { store.allocate (BUFFER_SIZE + 1, 1); }, + [&] (void) { store.allocate (BUFFER_SIZE + 1, 1); }, "excessive allocation throws bad_alloc" ); tap.expect_nothrow ( - [&] (void) { store.allocate (BUFFER_SIZE); }, + [&] (void) { store.allocate (BUFFER_SIZE); }, "maximum allocation succeeds" ); @@ -31,14 +31,14 @@ main (void) tap.expect_eq (store.remain (), 0u, "bytes remain matches"); tap.expect_throw ( - [&] (void) { store.allocate (1, 1); }, + [&] (void) { store.allocate (1, 1); }, "minimum allocation fails after exhaustion" ); store.reset (); tap.expect_nothrow ( - [&] (void) { store.allocate (1, 1); }, + [&] (void) { store.allocate (1, 1); }, "minimum allocation succeeds after reset" ); diff --git a/test/alloc/stack.cpp b/test/alloc/stack.cpp index 5e8d8d14..2bddbd1f 100644 --- a/test/alloc/stack.cpp +++ b/test/alloc/stack.cpp @@ -10,8 +10,8 @@ n_allocations (util::alloc::raw::stack &store, size_t alignment = alignof (std::max_align_t)) { for (unsigned i = 0; i < count; ++i) { - auto ptr = store.allocate (bytes, alignment); - store.deallocate (ptr, alignment); + auto ptr = store.allocate (bytes, alignment); + store.deallocate (ptr); } } @@ -40,7 +40,7 @@ main (void) // larger than total allocations should throw tap.expect_throw ( - [&store] (void) { store.allocate (BUFFER_AVAILABLE + 1, 1); }, + [&store] (void) { store.allocate (BUFFER_AVAILABLE + 1, 1); }, "excessive allocation throws bad_alloc" ); @@ -53,11 +53,11 @@ main (void) // perform two near maximum allocations and check for exhaustion through // bad_alloc - auto ptr = store.allocate (BUFFER_REQUEST); + auto ptr = store.allocate (BUFFER_REQUEST); (void)ptr; tap.expect_throw ( - [&store] (void) { store.allocate (BUFFER_REQUEST); }, + [&store] (void) { store.allocate (BUFFER_REQUEST); }, "bad_alloc thrown on exhaustion" );