Ticket #9334: 9334.patch

File 9334.patch, 22.6 KB (added by Antony Polukhin, 9 years ago)

More advanced patch, based on the previous one.

  • include/boost/circular_buffer/base.hpp

    From 0f66798d1decb6b25bdee27eafebbb3915500831 Mon Sep 17 00:00:00 2001
    From: Antony Polukhin <antoshkka@gmail.com>
    Date: Tue, 3 Dec 2013 13:40:58 +0400
    Subject: [PATCH 1/2] Fixed issues with allocators that do not return pointers,
     added tes case for such situations (refs #9334)
    
    ---
     include/boost/circular_buffer/base.hpp    | 40 +++++++-------
     include/boost/circular_buffer/details.hpp | 89 ++++++++++++++++++++-----------
     test/common.ipp                           | 89 ++++++++++++++++++++++++++++++-
     3 files changed, 166 insertions(+), 52 deletions(-)
    
    diff --git a/include/boost/circular_buffer/base.hpp b/include/boost/circular_buffer/base.hpp
    index b3cdf88..a80a103 100644
    a b public:  
    690690                        break;
    691691                    }
    692692                    if (is_uninitialized(dest)) {
    693                         ::new (dest) value_type(this_type::move_if_noexcept(*src));
     693                        cb_details::do_construct<value_type>(dest, this_type::move_if_noexcept(*src), m_alloc);
    694694                        ++constructed;
    695695                    } else {
    696696                        value_type tmp = this_type::move_if_noexcept(*src);
    public:  
    902902        iterator b = begin();
    903903        BOOST_TRY {
    904904            reset(buff,
    905                 cb_details::uninitialized_move_if_noexcept<value_type>(b, b + (std::min)(new_capacity, size()), buff),
     905                cb_details::uninitialized_move_if_noexcept(b, b + (std::min)(new_capacity, size()), buff, m_alloc),
    906906                new_capacity);
    907907        } BOOST_CATCH(...) {
    908908            deallocate(buff, new_capacity);
    public:  
    977977        pointer buff = allocate(new_capacity);
    978978        iterator e = end();
    979979        BOOST_TRY {
    980             reset(buff, cb_details::uninitialized_move_if_noexcept<value_type>(e - (std::min)(new_capacity, size()),
    981                 e, buff), new_capacity);
     980            reset(buff, cb_details::uninitialized_move_if_noexcept(e - (std::min)(new_capacity, size()),
     981                e, buff, m_alloc), new_capacity);
    982982        } BOOST_CATCH(...) {
    983983            deallocate(buff, new_capacity);
    984984            BOOST_RETHROW
    public:  
    11251125        initialize_buffer(cb.capacity());
    11261126        m_first = m_buff;
    11271127        BOOST_TRY {
    1128             m_last = cb_details::uninitialized_copy<value_type>(cb.begin(), cb.end(), m_buff);
     1128            m_last = cb_details::uninitialized_copy(cb.begin(), cb.end(), m_buff, m_alloc);
    11291129        } BOOST_CATCH(...) {
    11301130            deallocate(m_buff, cb.capacity());
    11311131            BOOST_RETHROW
    public:  
    12491249            return *this;
    12501250        pointer buff = allocate(cb.capacity());
    12511251        BOOST_TRY {
    1252             reset(buff, cb_details::uninitialized_copy<value_type>(cb.begin(), cb.end(), buff), cb.capacity());
     1252            reset(buff, cb_details::uninitialized_copy(cb.begin(), cb.end(), buff, m_alloc), cb.capacity());
    12531253        } BOOST_CATCH(...) {
    12541254            deallocate(buff, cb.capacity());
    12551255            BOOST_RETHROW
    private:  
    14461446            increment(m_last);
    14471447            m_first = m_last;
    14481448        } else {
    1449             ::new (m_last) value_type(static_cast<ValT>(item));
     1449            cb_details::do_construct<value_type>(m_last, static_cast<ValT>(item), m_alloc);
    14501450            increment(m_last);
    14511451            ++m_size;
    14521452        }       
    private:  
    14631463                m_last = m_first;
    14641464            } else {
    14651465                decrement(m_first);
    1466                 ::new (m_first) value_type(static_cast<ValT>(item));
     1466                cb_details::do_construct<value_type>(m_first, static_cast<ValT>(item), m_alloc);
    14671467                ++m_size;
    14681468            }
    14691469        } BOOST_CATCH(...) {
    private:  
    23972397            throw_exception(std::length_error("circular_buffer"));
    23982398#if BOOST_CB_ENABLE_DEBUG
    23992399        pointer p = (n == 0) ? 0 : m_alloc.allocate(n, 0);
    2400         std::memset(p, cb_details::UNINITIALIZED, sizeof(value_type) * n);
     2400        std::memset(boost::addressof(*p), cb_details::UNINITIALIZED, sizeof(value_type) * n);
    24012401        return p;
    24022402#else
    24032403        return (n == 0) ? 0 : m_alloc.allocate(n, 0);
    private:  
    24382438    */
    24392439    void construct_or_replace(bool construct, pointer pos, param_value_type item) {
    24402440        if (construct)
    2441             ::new (pos) value_type(item);
     2441            cb_details::do_construct<value_type>(pos, item, m_alloc);
    24422442        else
    24432443            replace(pos, item);
    24442444    }
    private:  
    24502450    */
    24512451    void construct_or_replace(bool construct, pointer pos, rvalue_type item) {
    24522452        if (construct)
    2453             ::new (pos) value_type(boost::move(item));
     2453            cb_details::do_construct<value_type>(pos, boost::move(item), m_alloc);
    24542454        else
    24552455            replace(pos, boost::move(item));
    24562456    }
    private:  
    24602460        m_alloc.destroy(p);
    24612461#if BOOST_CB_ENABLE_DEBUG
    24622462        invalidate_iterators(iterator(this, p));
    2463         std::memset(p, cb_details::UNINITIALIZED, sizeof(value_type));
     2463        std::memset(boost::addressof(*p), cb_details::UNINITIALIZED, sizeof(value_type));
    24642464#endif
    24652465    }
    24662466
    private:  
    25902590        if (buffer_capacity == 0)
    25912591            return;
    25922592        while (first != last && !full()) {
    2593             ::new (m_last) value_type(*first++);
     2593            cb_details::do_construct<value_type>(m_last, *first++, m_alloc);
    25942594            increment(m_last);
    25952595            ++m_size;
    25962596        }
    private:  
    26262626            m_size = distance;
    26272627        }
    26282628        BOOST_TRY {
    2629             m_last = cb_details::uninitialized_copy<value_type>(first, last, m_buff);
     2629            m_last = cb_details::uninitialized_copy(first, last, m_buff, m_alloc);
    26302630        } BOOST_CATCH(...) {
    26312631            deallocate(m_buff, buffer_capacity);
    26322632            BOOST_RETHROW
    private:  
    26802680        std::deque<value_type, allocator_type> tmp(first, last, m_alloc);
    26812681        size_type distance = tmp.size();
    26822682        assign_n(distance, distance,
    2683             cb_details::make_assign_range<value_type>
    2684                 (boost::make_move_iterator(tmp.begin()), boost::make_move_iterator(tmp.end())));
     2683            cb_details::make_assign_range
     2684                (boost::make_move_iterator(tmp.begin()), boost::make_move_iterator(tmp.end()), m_alloc));
    26852685    }
    26862686
    26872687    //! Specialized assign method.
    private:  
    26892689    void assign(ForwardIterator first, ForwardIterator last, const std::forward_iterator_tag&) {
    26902690        BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range
    26912691        size_type distance = std::distance(first, last);
    2692         assign_n(distance, distance, cb_details::make_assign_range<value_type>(first, last));
     2692        assign_n(distance, distance, cb_details::make_assign_range(first, last, m_alloc));
    26932693    }
    26942694
    26952695    //! Specialized assign method.
    private:  
    27322732            distance = new_capacity;
    27332733        }
    27342734        assign_n(new_capacity, distance,
    2735             cb_details::make_assign_range<value_type>(first, last));
     2735            cb_details::make_assign_range(first, last, m_alloc));
    27362736    }
    27372737
    27382738    //! Helper assign method.
    private:  
    28552855            pointer p = m_last;
    28562856            BOOST_TRY {
    28572857                for (; ii < construct; ++ii, increment(p))
    2858                     ::new (p) value_type(*wrapper());
     2858                    cb_details::do_construct<value_type>(p, *wrapper(), m_alloc);
    28592859                for (;ii < n; ++ii, increment(p))
    28602860                    replace(p, *wrapper());
    28612861            } BOOST_CATCH(...) {
    private:  
    29492949                for (;ii > construct; --ii, increment(p))
    29502950                    replace(p, *wrapper());
    29512951                for (; ii > 0; --ii, increment(p))
    2952                     ::new (p) value_type(*wrapper());
     2952                    cb_details::do_construct<value_type>(p, *wrapper(), m_alloc);
    29532953            } BOOST_CATCH(...) {
    29542954                size_type constructed = ii < construct ? construct - ii : 0;
    29552955                m_last = add(m_last, constructed);
  • include/boost/circular_buffer/details.hpp

    diff --git a/include/boost/circular_buffer/details.hpp b/include/boost/circular_buffer/details.hpp
    index 2ab1789..5d9c9b4 100644
    a b template<class ForwardIterator, class Diff, class T, class Alloc>  
    3838void uninitialized_fill_n_with_alloc(
    3939    ForwardIterator first, Diff n, const T& item, Alloc& alloc);
    4040
    41 template<class ValueType, class InputIterator, class ForwardIterator>
    42 ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator dest);
     41template<class InputIterator, class ForwardIterator, class Alloc>
     42ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator dest, Alloc& a);
     43
     44template<class InputIterator, class ForwardIterator, class Alloc>
     45ForwardIterator uninitialized_move_if_noexcept(InputIterator first, InputIterator last, ForwardIterator dest, Alloc& a);
     46
     47
     48//! Those `do_construct` methods are required because in C++03 default allocators
     49//! have `construct` method that accepts second parameter in as a const reference;
     50//! while move-only types emulated by Boost.Move require constructor that accepts
     51//! a non-const reference.
     52//!
     53//! So when we need to call `construct` and pointer to value_type is provided, we
     54//! assume that it is safe to call placement new instead of Alloc::construct.
     55//! Otherwise we are asume that user has made his own allocator or uses allocator
     56//! from other libraries. In that case it's users ability to provide Alloc::construct
     57//! with non-const reference parameter or just do not use move-only types.
     58template <class ValueType, class Alloc>
     59inline void do_construct(ValueType* p, BOOST_RV_REF(ValueType) item, Alloc&) {
     60    ::new (p) ValueType(boost::move(item));
     61}
     62
     63template <class ValueType, class Alloc>
     64inline void do_construct(ValueType* p, const ValueType& item, Alloc&) {
     65    ::new (p) ValueType(item);
     66}
    4367
    44 template<class ValueType, class InputIterator, class ForwardIterator>
    45 ForwardIterator uninitialized_move_if_noexcept(InputIterator first, InputIterator last, ForwardIterator dest);
     68template <class ValueType, class Alloc, class PointerT>
     69inline void do_construct(PointerT& p, BOOST_RV_REF(ValueType) item, Alloc& a) {
     70    a.construct(p, boost::move(item));
     71}
     72
     73template <class ValueType, class Alloc, class PointerT>
     74inline void do_construct(PointerT& p, const ValueType& item, Alloc& a) {
     75    a.construct(p, item);
     76}
    4677
    4778/*!
    4879    \struct const_traits
    private:  
    127158    \struct assign_range
    128159    \brief Helper functor for assigning range of items.
    129160*/
    130 template <class ValueType, class Iterator>
     161template <class Iterator, class Alloc>
    131162struct assign_range {
    132163    Iterator m_first;
    133164    Iterator m_last;
     165    Alloc&   m_alloc;
    134166
    135     assign_range(const Iterator& first, const Iterator& last) BOOST_NOEXCEPT
    136     : m_first(first), m_last(last) {}
     167    assign_range(const Iterator& first, const Iterator& last, Alloc& alloc)
     168        : m_first(first), m_last(last), m_alloc(alloc) {}
    137169
    138170    template <class Pointer>
    139171    void operator () (Pointer p) const {
    140         boost::cb_details::uninitialized_copy<ValueType>(m_first, m_last, p);
     172        boost::cb_details::uninitialized_copy(m_first, m_last, p, m_alloc);
    141173    }
    142174};
    143175
    144 template <class ValueType, class Iterator>
    145 inline assign_range<ValueType, Iterator> make_assign_range(const Iterator& first, const Iterator& last) {
    146     return assign_range<ValueType, Iterator>(first, last);
     176template <class Iterator, class Alloc>
     177inline assign_range<Iterator, Alloc> make_assign_range(const Iterator& first, const Iterator& last, Alloc& a) {
     178    return assign_range<Iterator, Alloc>(first, last, a);
    147179}
    148180
    149181/*!
    operator + (typename Traits::difference_type n, const iterator<Buff, Traits>& it  
    427459    \fn ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator dest)
    428460    \brief Equivalent of <code>std::uninitialized_copy</code> but with explicit specification of value type.
    429461*/
    430 template<class ValueType, class InputIterator, class ForwardIterator>
    431 inline ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator dest) {
    432     typedef ValueType value_type;
    433 
    434     // We do not use allocator.construct and allocator.destroy
    435     // because C++03 requires to take parameter by const reference but
    436     // Boost.move requires nonconst reference
     462template<class InputIterator, class ForwardIterator, class Alloc>
     463inline ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator dest, Alloc& a) {
    437464    ForwardIterator next = dest;
    438465    BOOST_TRY {
    439466        for (; first != last; ++first, ++dest)
    440             ::new (dest) value_type(*first);
     467            do_construct<typename Alloc::value_type>(dest, *first, a);
    441468    } BOOST_CATCH(...) {
    442469        for (; next != dest; ++next)
    443             next->~value_type();
     470            a.destroy(next);
    444471        BOOST_RETHROW
    445472    }
    446473    BOOST_CATCH_END
    447474    return dest;
    448475}
    449476
    450 template<class ValueType, class InputIterator, class ForwardIterator>
    451 ForwardIterator uninitialized_move_if_noexcept_impl(InputIterator first, InputIterator last, ForwardIterator dest,
     477template<class InputIterator, class ForwardIterator, class Alloc>
     478ForwardIterator uninitialized_move_if_noexcept_impl(InputIterator first, InputIterator last, ForwardIterator dest, Alloc& a,
    452479    true_type) {
    453480    for (; first != last; ++first, ++dest)
    454         ::new (dest) ValueType(boost::move(*first));
     481        do_construct<typename Alloc::value_type>(dest, boost::move(*first), a);
    455482    return dest;
    456483}
    457484
    458 template<class ValueType, class InputIterator, class ForwardIterator>
    459 ForwardIterator uninitialized_move_if_noexcept_impl(InputIterator first, InputIterator last, ForwardIterator dest,
     485template<class InputIterator, class ForwardIterator, class Alloc>
     486ForwardIterator uninitialized_move_if_noexcept_impl(InputIterator first, InputIterator last, ForwardIterator dest, Alloc& a,
    460487    false_type) {
    461     return uninitialized_copy<ValueType>(first, last, dest);
     488    return uninitialized_copy(first, last, dest, a);
    462489}
    463490
    464491/*!
    465492    \fn ForwardIterator uninitialized_move_if_noexcept(InputIterator first, InputIterator last, ForwardIterator dest)
    466493    \brief Equivalent of <code>std::uninitialized_copy</code> but with explicit specification of value type and moves elements if they have noexcept move constructors.
    467494*/
    468 template<class ValueType, class InputIterator, class ForwardIterator>
    469 ForwardIterator uninitialized_move_if_noexcept(InputIterator first, InputIterator last, ForwardIterator dest) {
    470     typedef typename boost::is_nothrow_move_constructible<ValueType>::type tag_t;
    471     return uninitialized_move_if_noexcept_impl<ValueType>(first, last, dest, tag_t());
     495template<class InputIterator, class ForwardIterator, class Alloc>
     496ForwardIterator uninitialized_move_if_noexcept(InputIterator first, InputIterator last, ForwardIterator dest, Alloc& a) {
     497    typedef typename boost::is_nothrow_move_constructible<typename Alloc::value_type>::type tag_t;
     498    return uninitialized_move_if_noexcept_impl(first, last, dest, a, tag_t());
    472499}
    473500
    474501/*!
    inline void uninitialized_fill_n_with_alloc(ForwardIterator first, Diff n, const  
    480507    ForwardIterator next = first;
    481508    BOOST_TRY {
    482509        for (; n > 0; ++first, --n)
    483             alloc.construct(first, item);
     510            do_construct<typename Alloc::value_type>(first, item, alloc);
    484511    } BOOST_CATCH(...) {
    485512        for (; next != first; ++next)
    486513            alloc.destroy(next);
  • test/common.ipp

    diff --git a/test/common.ipp b/test/common.ipp
    index 772b74f..67dd464 100644
    a b  
    1111#include <boost/type_traits/is_nothrow_move_assignable.hpp>
    1212#include <boost/type_traits/has_nothrow_constructor.hpp>
    1313
    14 void generic_test(CB_CONTAINER<MyInteger>& cb) {
     14template <class Alloc>
     15void generic_test(CB_CONTAINER<MyInteger, Alloc>& cb) {
    1516
    1617    vector<int> v;
    1718    v.push_back(11);
    void size_test() {  
    149150    generic_test(cb2);
    150151}
    151152
     153template<class T>
     154class my_allocator {
     155    typedef std::allocator<T> base_t;
     156    base_t base_;
     157public:
     158   typedef T                                    value_type;
     159
     160
     161   typedef value_type&         reference;
     162   typedef const value_type&   const_reference;
     163   typedef typename base_t::size_type               size_type;
     164   typedef typename base_t::difference_type         difference_type;
     165
     166   struct const_pointer;
     167   struct pointer {
     168       pointer(){}
     169       pointer(void* p) : hidden_ptr_((T*)p) {}
     170       difference_type operator-(const const_pointer& rhs) const { return hidden_ptr_ - rhs.hidden_ptr_; }
     171       difference_type operator-(pointer rhs) const { return hidden_ptr_ - rhs.hidden_ptr_; }
     172       pointer operator-(size_type rhs) const { return hidden_ptr_ - rhs; }
     173       bool operator == (pointer rhs) const { return hidden_ptr_ == rhs.hidden_ptr_; }
     174       bool operator != (pointer rhs) const { return hidden_ptr_ != rhs.hidden_ptr_; }
     175       bool operator < (pointer rhs) const { return hidden_ptr_ < rhs.hidden_ptr_; }
     176       bool operator >= (pointer rhs) const { return hidden_ptr_ >= rhs.hidden_ptr_; }
     177       pointer& operator++() { ++hidden_ptr_; return *this; }
     178       pointer& operator--() { --hidden_ptr_; return *this; }
     179       pointer& operator+=(size_type s) { hidden_ptr_ += s; return *this; }
     180       pointer operator+(size_type s) const { return hidden_ptr_ + s; }
     181       pointer operator++(int) { pointer p = *this; ++hidden_ptr_; return p; }
     182       pointer operator--(int) { pointer p = *this; --hidden_ptr_; return p; }
     183       T& operator*() const { return *hidden_ptr_; }
     184
     185       T* hidden_ptr_;
     186   };
     187
     188   struct const_pointer {
     189       const_pointer(){}
     190       const_pointer(pointer p) : hidden_ptr_(p.hidden_ptr_) {}
     191       const_pointer(const void* p) : hidden_ptr_((const T*)p) {}
     192       difference_type operator-(pointer rhs) const { return hidden_ptr_ - rhs.hidden_ptr_; }
     193       difference_type operator-(const_pointer rhs) const { return hidden_ptr_ - rhs.hidden_ptr_; }
     194       const_pointer operator-(size_type rhs) const { return hidden_ptr_ - rhs; }
     195       bool operator == (const_pointer rhs) const { return hidden_ptr_ == rhs.hidden_ptr_; }
     196       bool operator != (const_pointer rhs) const { return hidden_ptr_ != rhs.hidden_ptr_; }
     197       bool operator < (const_pointer rhs) const { return hidden_ptr_ < rhs.hidden_ptr_; }
     198       bool operator >= (const_pointer rhs) const { return hidden_ptr_ >= rhs.hidden_ptr_; }
     199       const_pointer& operator++() { ++hidden_ptr_; return *this; }
     200       const_pointer& operator--() { --hidden_ptr_; return *this; }
     201       const_pointer& operator+=(size_type s) { hidden_ptr_ += s; return hidden_ptr_; }
     202       const_pointer operator+(size_type s) const { return hidden_ptr_ + s; }
     203       const_pointer operator++(int) { const_pointer p = *this; ++hidden_ptr_; return p; }
     204       const_pointer operator--(int) { const_pointer p = *this; --hidden_ptr_; return p; }
     205       const T& operator*() const { return *hidden_ptr_; }
     206
     207       const T* hidden_ptr_;
     208   };
     209
     210   template<class T2>
     211   struct rebind
     212   {
     213      typedef my_allocator<T2>     other;
     214   };
     215
     216   size_type max_size() const
     217   {  return base_.max_size();   }
     218
     219   pointer allocate(size_type count, const void* hint = 0) {
     220      return pointer(base_.allocate(count, hint));
     221   }
     222
     223   void deallocate(const pointer &ptr, size_type s)
     224   {  base_.deallocate(ptr.hidden_ptr_, s);  }
     225
     226   template<class P>
     227   void construct(const pointer &ptr, BOOST_FWD_REF(P) p)
     228   {  ::new(ptr.hidden_ptr_) value_type(::boost::forward<P>(p));  }
     229
     230   void destroy(const pointer &ptr)
     231   {  (*ptr.hidden_ptr_).~value_type();  }
     232
     233};
     234
    152235void allocator_test() {
    153236
    154237    CB_CONTAINER<MyInteger> cb1(10, 0);
    void allocator_test() {  
    159242    alloc.max_size();
    160243
    161244    generic_test(cb1);
     245
     246   
     247    CB_CONTAINER<MyInteger, my_allocator<MyInteger> > cb_a(10, 0);
     248    generic_test(cb_a);
    162249}
    163250
    164251void begin_and_end_test() {
  • include/boost/circular_buffer/base.hpp

    -- 
    1.8.4.4
    
    
    From 4bdfcaaa088a15fcc2294a524453cf9740e5070a Mon Sep 17 00:00:00 2001
    From: Antony Polukhin <antoshkka@gmail.com>
    Date: Tue, 3 Dec 2013 15:44:43 +0400
    Subject: [PATCH 2/2] Fixed setting memory to '0xcc' in debug mode for
     non-pointer allocator::pointer types
    
    ---
     include/boost/circular_buffer/base.hpp  | 15 ++-------------
     include/boost/circular_buffer/debug.hpp | 21 +++++++++++++++++++++
     2 files changed, 23 insertions(+), 13 deletions(-)
    
    diff --git a/include/boost/circular_buffer/base.hpp b/include/boost/circular_buffer/base.hpp
    index a80a103..b3913d6 100644
    a b  
    3434#include <utility>
    3535#include <deque>
    3636#include <stdexcept>
    37 #if BOOST_CB_ENABLE_DEBUG
    38     #include <cstring>
    39 #endif
    4037#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205))
    4138    #include <stddef.h>
    4239#endif
    4340
    44 #if defined(BOOST_NO_STDC_NAMESPACE)
    45 namespace std {
    46     using ::memset;
    47 }
    48 #endif
    49 
    50 
    51 
    5241namespace boost {
    5342
    5443/*!
    private:  
    23972386            throw_exception(std::length_error("circular_buffer"));
    23982387#if BOOST_CB_ENABLE_DEBUG
    23992388        pointer p = (n == 0) ? 0 : m_alloc.allocate(n, 0);
    2400         std::memset(boost::addressof(*p), cb_details::UNINITIALIZED, sizeof(value_type) * n);
     2389        cb_details::do_fill_uninitialized_memory(p, sizeof(value_type) * n);
    24012390        return p;
    24022391#else
    24032392        return (n == 0) ? 0 : m_alloc.allocate(n, 0);
    private:  
    24602449        m_alloc.destroy(p);
    24612450#if BOOST_CB_ENABLE_DEBUG
    24622451        invalidate_iterators(iterator(this, p));
    2463         std::memset(boost::addressof(*p), cb_details::UNINITIALIZED, sizeof(value_type));
     2452        cb_details::do_fill_uninitialized_memory(p, sizeof(value_type));
    24642453#endif
    24652454    }
    24662455
  • include/boost/circular_buffer/debug.hpp

    diff --git a/include/boost/circular_buffer/debug.hpp b/include/boost/circular_buffer/debug.hpp
    index d3b6ef5..b6ab0fe 100644
    a b  
    1313    #pragma once
    1414#endif
    1515
     16#if BOOST_CB_ENABLE_DEBUG
     17#include <cstring>
     18
     19#if defined(BOOST_NO_STDC_NAMESPACE)
     20namespace std {
     21    using ::memset;
     22}
     23#endif
     24
     25#endif // BOOST_CB_ENABLE_DEBUG
    1626namespace boost {
    1727
    1828namespace cb_details {
    namespace cb_details {  
    2232// The value the uninitialized memory is filled with.
    2333const int UNINITIALIZED = 0xcc;
    2434
     35template <class T>
     36inline void do_fill_uninitialized_memory(T* data, std::size_t size_in_bytes) BOOST_NOEXCEPT {
     37    std::memset(static_cast<void*>(data), UNINITIALIZED, size_in_bytes);
     38}
     39
     40template <class T>
     41inline void do_fill_uninitialized_memory(T& /*data*/, std::size_t /*size_in_bytes*/) BOOST_NOEXCEPT {
     42    // Do nothing
     43}
     44
     45
    2546class debug_iterator_registry;
    2647
    2748/*!