Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r82042 - in sandbox/static_vector: boost boost/container test
From: adam.wulkiewicz_at_[hidden]
Date: 2012-12-16 19:20:45


Author: awulkiew
Date: 2012-12-16 19:20:44 EST (Sun, 16 Dec 2012)
New Revision: 82042
URL: http://svn.boost.org/trac/boost/changeset/82042

Log:
Two versions of static_vector merged into this one.
Andrew Hundt - https://github.com/ahundt/Boost.StaticVector/blob/master/StaticVector.hpp
Adam Wulkiewicz - https://svn.boost.org/svn/boost/sandbox-branches/geometry/index/boost/geometry/extensions/index/static_vector.hpp
Added:
   sandbox/static_vector/boost/
   sandbox/static_vector/boost/container/
   sandbox/static_vector/boost/container/static_vector.hpp (contents, props changed)
   sandbox/static_vector/test/
   sandbox/static_vector/test/Jamfile.v2 (contents, props changed)
   sandbox/static_vector/test/static_vector.cpp (contents, props changed)

Added: sandbox/static_vector/boost/container/static_vector.hpp
==============================================================================
--- (empty file)
+++ sandbox/static_vector/boost/container/static_vector.hpp 2012-12-16 19:20:44 EST (Sun, 16 Dec 2012)
@@ -0,0 +1,1128 @@
+// Boost.Container StaticVector
+//
+// Copyright (c) 2012 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011 Andrew Hundt, Carnegie Mellon University.
+//
+// Use, modification and distribution is subject to 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)
+
+#ifndef BOOST_CONTAINER_STATIC_VECTOR_HPP
+#define BOOST_CONTAINER_STATIC_VECTOR_HPP
+
+#include <cstddef>
+#include <stdexcept>
+
+#include <boost/config.hpp>
+
+#include <boost/iterator/reverse_iterator.hpp>
+#include <boost/integer.hpp>
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/and.hpp>
+#include <boost/mpl/or.hpp>
+
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <boost/type_traits/aligned_storage.hpp>
+#include <boost/type_traits/has_trivial_assign.hpp>
+#include <boost/type_traits/has_trivial_copy.hpp>
+#include <boost/type_traits/has_trivial_constructor.hpp>
+#include <boost/type_traits/has_trivial_destructor.hpp>
+
+namespace boost { namespace container {
+
+// Forward declaration
+namespace detail { namespace static_vector {
+
+struct error_handling;
+
+}} // namespace detail::static_vector
+
+// Eventually size_type_t = typename boost::uint_value_t<Capacity>::least
+// however it will probably be slower
+
+template <typename Value, std::size_t Capacity, typename StoredSizeType = std::size_t>
+class static_vector
+{
+ typedef detail::static_vector::error_handling errh;
+
+public:
+ typedef Value value_type;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef Value& reference;
+ typedef Value const& const_reference;
+ typedef Value * pointer;
+ typedef const Value* const_pointer;
+ typedef Value* iterator;
+ typedef const Value * const_iterator;
+ typedef boost::reverse_iterator<iterator> reverse_iterator;
+ typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ // nothrow
+ static_vector()
+ : m_size(0)
+ {}
+
+ // strong
+ explicit static_vector(size_type count)
+ : m_size(0)
+ {
+ resize(count); // may throw
+ }
+
+ // strong
+ static_vector(size_type count, value_type const& value)
+ : m_size(0)
+ {
+ resize(count, value); // may throw
+ }
+
+ // strong
+ static_vector(static_vector const& other)
+ : m_size(other.size())
+ {
+ this->uninitialized_copy(other.begin(), other.end(), this->begin()); // may throw
+ }
+
+ // strong
+ template <size_t C>
+ static_vector(static_vector<value_type, C> const& other)
+ : m_size(other.size())
+ {
+ errh::check_capacity(other.size()); // may throw
+
+ this->uninitialized_copy(other.begin(), other.end(), this->begin()); // may throw
+ }
+
+ // strong
+ template <typename Iterator>
+ static_vector(Iterator first, Iterator last)
+ : m_size(0)
+ {
+ // TODO - add MPL_ASSERT, check if Iterator is really an iterator
+ assign(first, last); // may throw
+ }
+
+ // basic
+ static_vector & operator=(static_vector const& other)
+ {
+ assign(other.begin(), other.end()); // may throw
+
+ return *this;
+ }
+
+ // basic
+ template <size_t C>
+ static_vector & operator=(static_vector<value_type, C> const& other)
+ {
+ assign(other.begin(), other.end()); // may throw
+
+ return *this;
+ }
+
+ // nothrow
+ ~static_vector()
+ {
+ this->destroy(this->begin(), this->end());
+ }
+
+ // basic
+ void swap(static_vector & other)
+ {
+ iterator it = this->begin();
+ iterator other_it = other.begin();
+
+ if ( this->size() < other.size() )
+ {
+ for (; it != this->end() ; ++it, ++other_it)
+ boost::swap(*it, *other_it); // may throw
+ this->uninitialized_copy(other_it, other.end(), it); // may throw
+ this->destroy(other_it, other.end());
+ boost::swap(m_size, other.m_size);
+ }
+ else
+ {
+ for (; other_it != other.end() ; ++it, ++other_it)
+ boost::swap(*it, *other_it); // may throw
+ this->uninitialized_copy(it, this->end(), other_it); // may throw
+ this->destroy(it, it->end());
+ boost::swap(m_size, other.m_size);
+ }
+ }
+
+ // strong
+ void resize(size_type count)
+ {
+ if ( count < m_size )
+ {
+ this->destroy(this->begin() + count, this->end());
+ }
+ else
+ {
+ errh::check_capacity(*this, count); // may throw
+
+ this->construct(this->end(), this->begin() + count); // may throw
+ }
+ m_size = count; // update end
+ }
+
+ // strong
+ void resize(size_type count, value_type const& value)
+ {
+ if ( count < m_size )
+ {
+ this->destroy(this->begin() + count, this->end());
+ }
+ else
+ {
+ errh::check_capacity(*this, count); // may throw
+
+ std::uninitialized_fill(this->end(), this->begin() + count, value); // may throw
+ }
+ m_size = count; // update end
+ }
+
+ // nothrow
+ void reserve(size_type count)
+ {
+ errh::check_capacity(*this, count); // may throw
+ }
+
+ // strong
+ void push_back(value_type const& value)
+ {
+ errh::check_capacity(*this, m_size + 1); // may throw
+
+ this->uninitialized_fill(this->end(), value); // may throw
+ ++m_size; // update end
+ }
+
+ // nothrow
+ void pop_back()
+ {
+ errh::check_empty(*this);
+
+ //--m_size; // update end
+ //this->destroy(this->end());
+
+ // safer and more intuitive version
+ this->destroy(this->end() - 1);
+ --m_size; // update end
+ }
+
+ // basic
+ void insert(iterator position, value_type const& value)
+ {
+ errh::check_iterator_end_eq(*this, position);
+ errh::check_capacity(*this, m_size + 1); // may throw
+
+ if ( position == this->end() )
+ {
+ this->uninitialized_fill(position, value); // may throw
+ ++m_size; // update end
+ }
+ else
+ {
+ // TODO - should following lines check for exception and revert to the old size?
+
+ this->uninitialized_fill(this->end(), *(this->end() - 1)); // may throw
+ ++m_size; // update end
+ this->move_backward(position, this->end() - 2, this->end() - 1); // may throw
+ this->fill(position, value); // may throw
+ }
+ }
+
+ // basic
+ void insert(iterator position, size_type count, value_type const& value)
+ {
+ errh::check_iterator_end_eq(*this, position);
+ errh::check_capacity(*this, m_size + count); // may throw
+
+ if ( position == this->end() )
+ {
+ std::uninitialized_fill(position, position + count, value); // may throw
+ m_size += count; // update end
+ }
+ else
+ {
+ difference_type to_move = std::distance(position, this->end());
+
+ // TODO - should following lines check for exception and revert to the old size?
+
+ if ( count < static_cast<size_type>(to_move) )
+ {
+ this->uninitialized_copy(this->end() - count, this->end(), this->end()); // may throw
+ m_size += count; // update end
+ this->move_backward(position, position + to_move - count, this->end() - count); // may throw
+ std::fill_n(position, count, value); // may throw
+ }
+ else
+ {
+ std::uninitialized_fill(this->end(), position + count, value); // may throw
+ m_size += count - to_move; // update end
+ this->uninitialized_copy(position, position + to_move, position + count); // may throw
+ m_size += to_move; // update end
+ std::fill_n(position, to_move, value); // may throw
+ }
+ }
+ }
+
+ // basic
+ template <typename Iterator>
+ void insert(iterator position, Iterator first, Iterator last)
+ {
+ // TODO - add MPL_ASSERT, check if Iterator is really an iterator
+
+ typedef typename boost::iterator_traversal<Iterator>::type traversal;
+ this->insert_dispatch(position, first, last, traversal());
+ }
+
+ // basic
+ void erase(iterator position)
+ {
+ errh::check_iterator_end_neq(*this, position);
+
+ this->move(position + 1, this->end(), position); // may throw
+ this->destroy(this->end() - 1);
+ --m_size;
+ }
+
+ // basic
+ void erase(iterator first, iterator last)
+ {
+ errh::check_iterator_end_eq(*this, first);
+ errh::check_iterator_end_eq(*this, last);
+
+ difference_type n = std::distance(first, last);
+ //BOOST_ASSERT_MSG(0 <= n, "invalid range");
+
+ this->move(last, this->end(), first); // may throw
+ this->destroy(this->end() - n, this->end());
+ m_size -= n;
+ }
+
+ // basic
+ template <typename Iterator>
+ void assign(Iterator first, Iterator last)
+ {
+ // TODO - add MPL_ASSERT, check if Iterator is really an iterator
+
+ typedef typename boost::iterator_traversal<Iterator>::type traversal;
+ this->assign_dispatch(first, last, traversal()); // may throw
+ }
+
+ // basic
+ void assign(size_type count, value_type const& value)
+ {
+ if ( count < m_size )
+ {
+ std::fill_n(this->begin(), count, value);
+ this->destroy(this->begin() + count, this->end());
+ }
+ else
+ {
+ errh::check_capacity(*this, count); // may throw
+
+ std::fill_n(this->begin(), m_size, value);
+ std::uninitialized_fill(this->end(), this->begin() + count, value); // may throw
+ }
+ m_size = count; // update end
+ }
+
+ // nothrow
+ void clear()
+ {
+ this->destroy(this->begin(), this->end());
+ m_size = 0; // update end
+ }
+
+ // strong
+ Value & at(size_type i)
+ {
+ errh::check_index_throwing(*this, i); // may throw
+ return *(this->begin() + i);
+ }
+
+ // strong
+ Value const& at(size_type i) const
+ {
+ errh::check_index_throwing(*this, i); // may throw
+ return *(this->begin() + i);
+ }
+
+ // nothrow
+ Value & operator[](size_type i)
+ {
+ errh::check_index(*this, i);
+ return *(this->begin() + i);
+ }
+
+ // nothrow
+ Value const& operator[](size_type i) const
+ {
+ errh::check_index(*this, i);
+ return *(this->begin() + i);
+ }
+
+ // nothrow
+ Value & front()
+ {
+ errh::check_empty(*this);
+ return *(this->begin());
+ }
+
+ // nothrow
+ Value const& front() const
+ {
+ errh::check_empty(*this);
+ return *(this->begin());
+ }
+
+ // nothrow
+ Value & back()
+ {
+ errh::check_empty(*this);
+ return *(this->end() - 1);
+ }
+
+ // nothrow
+ Value const& back() const
+ {
+ errh::check_empty(*this);
+ return *(this->end() - 1);
+ }
+
+ // nothrow
+ Value * data() { return this->ptr(); }
+ const Value * data() const { return this->ptr(); }
+
+ // nothrow
+ iterator begin() { return this->ptr(); }
+ const_iterator begin() const { return this->ptr(); }
+ const_iterator cbegin() const { return this->ptr(); }
+ iterator end() { return this->begin() + m_size; }
+ const_iterator end() const { return this->begin() + m_size; }
+ const_iterator cend() const { return this->cbegin() + m_size; }
+ // nothrow
+ reverse_iterator rbegin() { return reverse_iterator(this->end()); }
+ const_reverse_iterator rbegin() const { return reverse_iterator(this->end()); }
+ const_reverse_iterator crbegin() const { return reverse_iterator(this->end()); }
+ reverse_iterator rend() { return reverse_iterator(this->begin()); }
+ const_reverse_iterator rend() const { return reverse_iterator(this->begin()); }
+ const_reverse_iterator crend() const { return reverse_iterator(this->begin()); }
+
+ // nothrow
+ size_type capacity() const { return Capacity; }
+ size_type max_size() const { return Capacity; }
+ size_type size() const { return m_size; }
+ bool empty() const { return 0 == m_size; }
+
+private:
+
+ // insert
+
+ template <typename Iterator>
+ void insert_dispatch(iterator position, Iterator first, Iterator last, boost::random_access_traversal_tag const&)
+ {
+ errh::check_iterator_end_eq(*this, position);
+
+ difference_type count = std::distance(first, last);
+
+ errh::check_capacity(*this, m_size + count); // may throw
+
+ if ( position == this->end() )
+ {
+ this->uninitialized_copy(first, last, position); // may throw
+ m_size += count; // update end
+ }
+ else
+ {
+ this->insert_in_the_middle(position, first, last, count); // may throw
+ }
+ }
+
+ template <typename Iterator, typename Traversal>
+ void insert_dispatch(iterator position, Iterator first, Iterator last, Traversal const& /*not_random_access*/)
+ {
+ errh::check_iterator_end_eq(*this, position);
+
+ if ( position == this->end() )
+ {
+ std::pair<bool, size_type> copy_data =
+ this->uninitialized_copy_checked(first, last, position, std::distance(position, this->begin() + Capacity)); // may throw
+
+ errh::check_capacity(*this, copy_data.first ? m_size + copy_data.second : Capacity + 1); // may throw
+
+ m_size += copy_data.second;
+ }
+ else
+ {
+ difference_type count = std::distance(first, last);
+
+ errh::check_capacity(*this, m_size + count); // may throw
+
+ this->insert_in_the_middle(position, first, last, count); // may throw
+ }
+ }
+
+ template <typename Iterator>
+ void insert_in_the_middle(iterator position, Iterator first, Iterator last, difference_type count)
+ {
+ difference_type to_move = std::distance(position, this->end());
+
+ // TODO - should following lines check for exception and revert to the old size?
+
+ if ( count < to_move )
+ {
+ this->uninitialized_copy(this->end() - count, this->end(), this->end()); // may throw
+ m_size += count; // update end
+ this->move_backward(position, position + to_move - count, this->end() - count); // may throw
+ this->copy(first, last, position); // may throw
+ }
+ else
+ {
+ Iterator middle_iter = first;
+ std::advance(middle_iter, to_move);
+
+ this->uninitialized_copy(middle_iter, last, this->end()); // may throw
+ m_size += count - to_move; // update end
+ this->uninitialized_copy(position, position + to_move, position + count); // may throw
+ m_size += to_move; // update end
+ this->copy(first, middle_iter, position) ; // may throw
+ }
+ }
+
+ // assign
+
+ template <typename Iterator>
+ void assign_dispatch(Iterator first, Iterator last, boost::random_access_traversal_tag const& /*not_random_access*/)
+ {
+ size_type s = std::distance(first, last);
+
+ errh::check_capacity(*this, s); // may throw
+
+ if ( m_size <= s )
+ {
+ this->copy(first, first + m_size, this->begin()); // may throw
+ // TODO - perform uninitialized_copy first?
+ this->uninitialized_copy(first + m_size, last, this->end()); // may throw
+ }
+ else
+ {
+ this->copy(first, last, this->begin()); // may throw
+ this->destroy(this->begin() + s, this->end());
+ }
+ m_size = s; // update end
+ }
+
+ template <typename Iterator, typename Traversal>
+ void assign_dispatch(Iterator first, Iterator last, Traversal const& /*not_random_access*/)
+ {
+ size_type s = 0;
+ iterator it = this->begin();
+
+ for ( ; it != this->end() && first != last ; ++it, ++first, ++s )
+ *it = *first; // may throw
+
+ this->destroy(it, this->end());
+
+ std::pair<bool, size_type> copy_data =
+ this->uninitialized_copy_checked(first, last, it, std::distance(it, this->begin() + Capacity)); // may throw
+ s += copy_data.second;
+
+ errh::check_capacity(*this, copy_data.first ? s : Capacity + 1); // may throw
+
+ m_size = s; // update end
+ }
+
+ // uninitialized_copy_checked
+
+ template <typename Iterator>
+ std::pair<bool, size_type> uninitialized_copy_checked(Iterator first, Iterator last, iterator dest, size_type max_count)
+ {
+ size_type count = 0;
+ iterator it = dest;
+ try
+ {
+ for ( ; first != last ; ++it, ++first, ++count )
+ {
+ if ( max_count <= count )
+ return std::make_pair(false, count);
+
+ this->uninitialized_fill(it, *first); // may throw
+ }
+ }
+ catch(...)
+ {
+ this->destroy(dest, it);
+ throw;
+ }
+ return std::make_pair(true, count);
+ }
+
+ // copy
+
+ template <typename Iterator>
+ void copy(Iterator first, Iterator last, iterator dst)
+ {
+ typedef typename
+ mpl::and_<
+ has_trivial_assign<value_type>,
+ mpl::or_<
+ is_same<Iterator, value_type *>,
+ is_same<Iterator, const value_type *>
+ >
+ >::type
+ use_memcpy;
+
+ this->copy_dispatch(first, last, dst, use_memcpy()); // may throw
+ }
+
+ void copy_dispatch(const value_type * first, const value_type * last, value_type * dst,
+ boost::mpl::bool_<true> const& /*use_memcpy*/)
+ {
+ ::memcpy(dst, first, sizeof(value_type) * std::distance(first, last));
+ }
+
+ template <typename Iterator>
+ void copy_dispatch(Iterator first, Iterator last, value_type * dst,
+ boost::mpl::bool_<false> const& /*use_memcpy*/)
+ {
+ std::copy(first, last, dst); // may throw
+ }
+
+ // uninitialized_copy
+
+ template <typename Iterator>
+ void uninitialized_copy(Iterator first, Iterator last, iterator dst)
+ {
+ typedef typename
+ mpl::and_<
+ has_trivial_copy<value_type>,
+ mpl::or_<
+ is_same<Iterator, value_type *>,
+ is_same<Iterator, const value_type *>
+ >
+ >::type
+ use_memcpy;
+
+ this->uninitialized_copy_dispatch(first, last, dst, use_memcpy()); // may throw
+ }
+
+ void uninitialized_copy_dispatch(const value_type * first, const value_type * last, value_type * dst,
+ boost::mpl::bool_<true> const& /*use_memcpy*/)
+ {
+ ::memcpy(dst, first, sizeof(value_type) * std::distance(first, last));
+ }
+
+ template <typename Iterator>
+ void uninitialized_copy_dispatch(Iterator first, Iterator last, value_type * dst,
+ boost::mpl::bool_<false> const& /*use_memcpy*/)
+ {
+ std::uninitialized_copy(first, last, dst); // may throw
+ }
+
+ // uninitialized_fill
+
+ template <typename V>
+ void uninitialized_fill(iterator dst, V const& v)
+ {
+ typedef typename
+ mpl::and_<
+ has_trivial_copy<value_type>,
+ is_same<Value, value_type>
+ >::type
+ use_memcpy;
+
+ uninitialized_fill_dispatch(dst, v, use_memcpy()); // may throw
+ }
+
+ void uninitialized_fill_dispatch(value_type * ptr, value_type const& v,
+ boost::mpl::bool_<true> const& /*use_memcpy*/)
+ {
+ // TODO - check if value_type has operator& defined and call this version only if it hasn't
+ const value_type * vptr = &v;
+ ::memcpy(ptr, vptr, sizeof(value_type));
+ }
+
+ template <typename V>
+ void uninitialized_fill_dispatch(value_type * ptr, V const& v,
+ boost::mpl::bool_<false> const& /*use_memcpy*/)
+ {
+ new (ptr) value_type(v); // may throw
+ }
+
+ // move
+
+ void move(iterator first, iterator last, iterator dst)
+ {
+ this->move_dispatch(first, last, dst, has_trivial_assign<value_type>()); // may throw
+ }
+
+ void move_dispatch(value_type * first, value_type * last, value_type * dst,
+ boost::true_type const& /*has_trivial_assign*/)
+ {
+ ::memmove(dst, first, sizeof(value_type) * std::distance(first, last));
+ }
+
+ void move_dispatch(value_type * first, value_type * last, value_type * dst,
+ boost::false_type const& /*has_trivial_assign*/)
+ {
+ std::copy(first, last, dst); // may throw
+ }
+
+ // move_backward
+
+ void move_backward(iterator first, iterator last, iterator dst)
+ {
+ this->move_backward_dispatch(first, last, dst, has_trivial_assign<value_type>()); // may throw
+ }
+
+ void move_backward_dispatch(value_type * first, value_type * last, value_type * dst,
+ boost::true_type const& /*has_trivial_assign*/)
+ {
+ difference_type n = std::distance(first, last);
+ ::memmove(dst - n, first, sizeof(value_type) * n);
+ }
+
+ void move_backward_dispatch(value_type * first, value_type * last, value_type * dst,
+ boost::false_type const& /*has_trivial_assign*/)
+ {
+ std::copy_backward(first, last, dst); // may throw
+ }
+
+ // uninitialized_fill
+
+ template <typename V>
+ void fill(iterator dst, V const& v)
+ {
+ fill_dispatch(dst, v, has_trivial_assign<value_type>()); // may throw
+ }
+
+ void fill_dispatch(value_type * ptr, value_type const& v,
+ boost::true_type const& /*has_trivial_assign*/)
+ {
+ // TODO - check if value_type has operator& defined and call this version only if it hasn't
+ const value_type * vptr = &v;
+ ::memcpy(ptr, vptr, sizeof(value_type));
+ }
+
+ template <typename V>
+ void fill_dispatch(value_type * ptr, V const& v,
+ boost::false_type const& /*has_trivial_assign*/)
+ {
+ *ptr = v; // may throw
+ }
+
+ // destroy
+
+ void destroy(iterator first, iterator last)
+ {
+ this->destroy_dispatch(first, last, has_trivial_destructor<value_type>());
+ }
+
+ void destroy_dispatch(value_type * /*first*/, value_type * /*last*/,
+ boost::true_type const& /*has_trivial_destructor*/)
+ {}
+
+ void destroy_dispatch(value_type * first, value_type * last,
+ boost::false_type const& /*has_trivial_destructor*/)
+ {
+ for ( ; first != last ; ++first )
+ first->~value_type();
+ }
+
+ // destroy
+
+ void destroy(iterator it)
+ {
+ this->destroy_dispatch(it, has_trivial_destructor<value_type>());
+ }
+
+ void destroy_dispatch(value_type * /*ptr*/,
+ boost::true_type const& /*has_trivial_destructor*/)
+ {}
+
+ void destroy_dispatch(value_type * ptr,
+ boost::false_type const& /*has_trivial_destructor*/)
+ {
+ ptr->~value_type();
+ }
+
+ // construct
+
+ void construct(iterator first, iterator last)
+ {
+ this->construct_dispatch(first, last, has_trivial_constructor<value_type>()); // may throw
+ }
+
+ void construct_dispatch(value_type * /*first*/, value_type * /*last*/,
+ boost::true_type const& /*has_trivial_constructor*/)
+ {}
+
+ void construct_dispatch(value_type * first, value_type * last,
+ boost::false_type const& /*has_trivial_constructor*/)
+ {
+ value_type * it = first;
+ try
+ {
+ for ( ; it != last ; ++it )
+ new (it) value_type(); // may throw
+ }
+ catch(...)
+ {
+ this->destroy(first, it);
+ throw;
+ }
+ }
+
+ Value * ptr()
+ {
+ return (reinterpret_cast<Value*>(m_storage.address()));
+ }
+
+ const Value * ptr() const
+ {
+ return (reinterpret_cast<const Value*>(m_storage.address()));
+ }
+
+ boost::aligned_storage<
+ sizeof(Value[Capacity]),
+ boost::alignment_of<Value[Capacity]>::value
+ > m_storage;
+ StoredSizeType m_size;
+};
+
+#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+template<typename Value, typename StoredSizeType>
+class static_vector<Value, 0, StoredSizeType>
+{
+ typedef detail::static_vector::error_handling errh;
+
+public:
+ typedef Value value_type;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef Value& reference;
+ typedef Value const& const_reference;
+ typedef Value * pointer;
+ typedef const Value* const_pointer;
+ typedef Value* iterator;
+ typedef const Value * const_iterator;
+ typedef boost::reverse_iterator<iterator> reverse_iterator;
+ typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ // nothrow
+ static_vector() {}
+
+ // strong
+ explicit static_vector(size_type count)
+ {
+ errh::check_capacity(*this, count); // may throw
+ }
+
+ // strong
+ static_vector(size_type count, value_type const& value)
+ {
+ errh::check_capacity(*this, count); // may throw
+ }
+
+ // strong
+ static_vector(static_vector const& other)
+ {
+ //errh::check_capacity(*this, count);
+ }
+
+ // strong
+ template <size_t C>
+ static_vector(static_vector<value_type, C> const& other)
+ {
+ errh::check_capacity(*this, other.size()); // may throw
+ }
+
+ // strong
+ template <typename Iterator>
+ static_vector(Iterator first, Iterator last)
+ {
+ errh::check_capacity(*this, std::distance(first, last)); // may throw
+ }
+
+ // basic
+ static_vector & operator=(static_vector const& other)
+ {
+ //errh::check_capacity(*this, other.size());
+ return *this;
+ }
+
+ // basic
+ template <size_t C>
+ static_vector & operator=(static_vector<value_type, C> const& other)
+ {
+ errh::check_capacity(*this, other.size()); // may throw
+ return *this;
+ }
+
+ // nothrow
+ ~static_vector() {}
+
+ // strong
+ void resize(size_type count)
+ {
+ errh::check_capacity(*this, count); // may throw
+ }
+
+ // strong
+ void resize(size_type count, value_type const& value)
+ {
+ errh::check_capacity(*this, count); // may throw
+ }
+
+ // nothrow
+ void reserve(size_type count)
+ {
+ errh::check_capacity(*this, count); // may throw
+ }
+
+ // strong
+ void push_back(value_type const& value)
+ {
+ errh::check_capacity(*this, 1); // may throw
+ }
+
+ // nothrow
+ void pop_back()
+ {
+ errh::check_empty(*this);
+ }
+
+ // basic
+ void insert(iterator position, value_type const& value)
+ {
+ errh::check_iterator_end_eq(*this, position);
+ errh::check_capacity(*this, 1); // may throw
+ }
+
+ // basic
+ void insert(iterator position, size_type count, value_type const& value)
+ {
+ errh::check_iterator_end_eq(*this, position);
+ errh::check_capacity(*this, count); // may throw
+ }
+
+ // basic
+ template <typename Iterator>
+ void insert(iterator position, Iterator first, Iterator last)
+ {
+ // TODO - add MPL_ASSERT, check if Iterator is really an iterator
+ typedef typename boost::iterator_traversal<Iterator>::type traversal;
+ errh::check_capacity(*this, std::distance(first, last)); // may throw
+ }
+
+ // basic
+ void erase(iterator position)
+ {
+ errh::check_iterator_end_neq(*this, position);
+ }
+
+ // basic
+ void erase(iterator first, iterator last)
+ {
+ errh::check_iterator_end_eq(*this, first);
+ errh::check_iterator_end_eq(*this, last);
+
+ //BOOST_ASSERT_MSG(0 <= n, "invalid range");
+ }
+
+ // basic
+ template <typename Iterator>
+ void assign(Iterator first, Iterator last)
+ {
+ // TODO - add MPL_ASSERT, check if Iterator is really an iterator
+ typedef typename boost::iterator_traversal<Iterator>::type traversal;
+ errh::check_capacity(*this, std::distance(first, last)); // may throw
+ }
+
+ // basic
+ void assign(size_type count, value_type const& value)
+ {
+ errh::check_capacity(*this, count); // may throw
+ }
+
+ // nothrow
+ void clear() {}
+
+ // strong
+ Value & at(size_type i)
+ {
+ errh::check_index_throwing(*this, i); // may throw
+ return *(this->begin() + i);
+ }
+
+ // strong
+ Value const& at(size_type i) const
+ {
+ errh::check_index_throwing(*this, i); // may throw
+ return *(this->begin() + i);
+ }
+
+ // nothrow
+ Value & operator[](size_type i)
+ {
+ errh::check_index(*this, i);
+ return *(this->begin() + i);
+ }
+
+ // nothrow
+ Value const& operator[](size_type i) const
+ {
+ errh::check_index(*this, i);
+ return *(this->begin() + i);
+ }
+
+ // nothrow
+ Value & front()
+ {
+ errh::check_empty(*this);
+ return *(this->begin());
+ }
+
+ // nothrow
+ Value const& front() const
+ {
+ errh::check_empty(*this);
+ return *(this->begin());
+ }
+
+ // nothrow
+ Value & back()
+ {
+ errh::check_empty(*this);
+ return *(this->end() - 1);
+ }
+
+ // nothrow
+ Value const& back() const
+ {
+ errh::check_empty(*this);
+ return *(this->end() - 1);
+ }
+
+ // nothrow
+ Value * data() { return this->ptr(); }
+ const Value * data() const { return this->ptr(); }
+
+ // nothrow
+ iterator begin() { return this->ptr(); }
+ const_iterator begin() const { return this->ptr(); }
+ const_iterator cbegin() const { return this->ptr(); }
+ iterator end() { return this->begin(); }
+ const_iterator end() const { return this->begin(); }
+ const_iterator cend() const { return this->cbegin(); }
+ // nothrow
+ reverse_iterator rbegin() { return reverse_iterator(this->end()); }
+ const_reverse_iterator rbegin() const { return reverse_iterator(this->end()); }
+ const_reverse_iterator crbegin() const { return reverse_iterator(this->end()); }
+ reverse_iterator rend() { return reverse_iterator(this->begin()); }
+ const_reverse_iterator rend() const { return reverse_iterator(this->begin()); }
+ const_reverse_iterator crend() const { return reverse_iterator(this->begin()); }
+
+ // nothrow
+ size_type capacity() const { return 0; }
+ size_type max_size() const { return 0; }
+ size_type size() const { return 0; }
+ bool empty() const { return true; }
+
+private:
+
+ Value * ptr()
+ {
+ return (reinterpret_cast<Value*>(this));
+ }
+
+ const Value * ptr() const
+ {
+ return (reinterpret_cast<const Value*>(this));
+ }
+};
+
+#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+
+namespace detail { namespace static_vector {
+
+struct error_handling
+{
+ template <typename V, std::size_t Capacity, typename S>
+ static void check_capacity(container::static_vector<V, Capacity, S> const& v,
+ typename container::static_vector<V, Capacity, S>::size_type s)
+ {
+ //BOOST_ASSERT_MSG(s <= Capacity, "size can't exceed the capacity");
+ if ( Capacity < s )
+ throw std::bad_alloc();
+ }
+
+ template <typename V, std::size_t C, typename S>
+ static void check_index_throwing(container::static_vector<V, C, S> const& v,
+ typename container::static_vector<V, C, S>::size_type i)
+ {
+ if ( v.size() <= i )
+ throw std::out_of_range("index out of bounds");
+ }
+
+ template <typename V, std::size_t C, typename S>
+ static void check_index(container::static_vector<V, C, S> const& v,
+ typename container::static_vector<V, C, S>::size_type i)
+ {
+ BOOST_ASSERT_MSG(i < v.size(), "index out of bounds");
+ }
+
+ template <typename V, std::size_t C, typename S>
+ static void check_empty(container::static_vector<V, C, S> const& v)
+ {
+ BOOST_ASSERT_MSG(0 < v.size(), "the container is empty");
+ }
+
+ template <typename V, std::size_t C, typename S>
+ static void check_iterator_end_neq(container::static_vector<V, C, S> const& v,
+ typename container::static_vector<V, C, S>::const_iterator position)
+ {
+ BOOST_ASSERT_MSG(v.begin() <= position && position < v.end(), "iterator out of bounds");
+
+ /*BOOST_GEOMETRY_INDEX_ASSERT_UNUSED_PARAM(
+ difference_type dist = std::distance(this->begin(), position);
+ )
+ BOOST_ASSERT_MSG(
+ 0 <= dist &&
+ ( sizeof(dist) <= sizeof(m_size) ?
+ (static_cast<size_type>(dist) < m_size) :
+ ( dist < static_cast<difference_type>(m_size))
+ ), "invalid iterator"
+ );*/
+ }
+
+ template <typename V, std::size_t C, typename S>
+ static void check_iterator_end_eq(container::static_vector<V, C, S> const& v,
+ typename container::static_vector<V, C, S>::const_iterator position)
+ {
+ BOOST_ASSERT_MSG(v.begin() <= position && position <= v.end(), "iterator out of bounds");
+
+ /*BOOST_GEOMETRY_INDEX_ASSERT_UNUSED_PARAM(
+ difference_type dist = std::distance(this->begin(), position);
+ )
+ BOOST_ASSERT_MSG(
+ 0 <= dist &&
+ ( sizeof(dist) <= sizeof(m_size) ?
+ (static_cast<size_type>(dist) <= m_size) :
+ ( dist <= static_cast<difference_type>(m_size))
+ ), "invalid iterator"
+ );*/
+ }
+};
+
+}} // namespace detail::static_vector
+
+}} // namespace boost::container
+
+#endif // BOOST_CONTAINER_STATIC_VECTOR_HPP

Added: sandbox/static_vector/test/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/static_vector/test/Jamfile.v2 2012-12-16 19:20:44 EST (Sun, 16 Dec 2012)
@@ -0,0 +1,23 @@
+# Boost.Container StaticVector
+#
+# Copyright (c) 2012 Adam Wulkiewicz, Lodz, Poland.
+#
+# Use, modification and distribution is subject to 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)
+
+import testing ;
+
+project boost-container-static_vector-test
+ :
+ requirements
+ <include>.
+ <include>..
+ <include>../..
+ <toolset>msvc:<asynch-exceptions>on
+ ;
+
+test-suite boost-container-static_vector
+ :
+ [ run static_vector.cpp ]
+ ;

Added: sandbox/static_vector/test/static_vector.cpp
==============================================================================
--- (empty file)
+++ sandbox/static_vector/test/static_vector.cpp 2012-12-16 19:20:44 EST (Sun, 16 Dec 2012)
@@ -0,0 +1,556 @@
+// Boost.Geometry Index
+// Unit Test
+
+// Copyright (c) 2011-2012 Adam Wulkiewicz, Lodz, Poland.
+
+// Use, modification and distribution is subject to 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)
+
+#include <boost/test/included/test_exec_monitor.hpp>
+#include <boost/test/impl/execution_monitor.ipp>
+
+#include <boost/container/static_vector.hpp>
+
+using namespace boost::container;
+
+class value_ndc
+{
+public:
+ explicit value_ndc(int a) : aa(a) {}
+ ~value_ndc() {}
+ bool operator==(value_ndc const& v) const { return aa == v.aa; }
+private:
+ value_ndc(value_ndc const&) {}
+ value_ndc & operator=(value_ndc const&) { return *this; }
+ int aa;
+};
+
+class value_nd
+{
+public:
+ explicit value_nd(int a) : aa(a) {}
+ ~value_nd() {}
+ bool operator==(value_nd const& v) const { return aa == v.aa; }
+private:
+ int aa;
+};
+
+class value_nc
+{
+public:
+ explicit value_nc(int a = 0) : aa(a) {}
+ ~value_nc() {}
+ bool operator==(value_nc const& v) const { return aa == v.aa; }
+private:
+ value_nc(value_nc const&) {}
+ value_nc & operator=(value_ndc const&) { return *this; }
+ int aa;
+};
+
+class counting_value
+{
+public:
+ explicit counting_value(int a = 0) : aa(a) { ++c(); }
+ counting_value(counting_value const& v) : aa(v.aa) { ++c(); }
+ counting_value & operator=(counting_value const& v) { aa = v.aa; return *this; }
+ ~counting_value() { --c(); }
+ bool operator==(counting_value const& v) const { return aa == v.aa; }
+ static size_t count() { return c(); }
+private:
+ static size_t & c() { static size_t co = 0; return co; }
+ int aa;
+};
+
+template <typename T, size_t N>
+void test_ctor_ndc()
+{
+ static_vector<T, N> s;
+ BOOST_CHECK(s.size() == 0);
+ BOOST_CHECK(s.capacity() == N);
+ BOOST_CHECK_THROW( s.at(0), std::out_of_range );
+}
+
+template <typename T, size_t N>
+void test_ctor_nc(size_t n)
+{
+ static_vector<T, N> s(n);
+ BOOST_CHECK(s.size() == n);
+ BOOST_CHECK(s.capacity() == N);
+ BOOST_CHECK_THROW( s.at(n), std::out_of_range );
+ if ( 1 < n )
+ {
+ s[0] = T(10);
+ BOOST_CHECK(T(10) == s[0]);
+ BOOST_CHECK(T(10) == s.at(0));
+ s.at(1) = T(20);
+ BOOST_CHECK(T(20) == s[1]);
+ BOOST_CHECK(T(20) == s.at(1));
+ }
+}
+
+template <typename T, size_t N>
+void test_ctor_nd(size_t n, T const& v)
+{
+ static_vector<T, N> s(n, v);
+ BOOST_CHECK(s.size() == n);
+ BOOST_CHECK(s.capacity() == N);
+ BOOST_CHECK_THROW( s.at(n), std::out_of_range );
+ if ( 1 < n )
+ {
+ BOOST_CHECK(v == s[0]);
+ BOOST_CHECK(v == s.at(0));
+ BOOST_CHECK(v == s[1]);
+ BOOST_CHECK(v == s.at(1));
+ s[0] = T(10);
+ BOOST_CHECK(T(10) == s[0]);
+ BOOST_CHECK(T(10) == s.at(0));
+ s.at(1) = T(20);
+ BOOST_CHECK(T(20) == s[1]);
+ BOOST_CHECK(T(20) == s.at(1));
+ }
+}
+
+template <typename T, size_t N>
+void test_resize_nc(size_t n)
+{
+ static_vector<T, N> s;
+
+ s.resize(n);
+ BOOST_CHECK(s.size() == n);
+ BOOST_CHECK(s.capacity() == N);
+ BOOST_CHECK_THROW( s.at(n), std::out_of_range );
+ if ( 1 < n )
+ {
+ s[0] = T(10);
+ BOOST_CHECK(T(10) == s[0]);
+ BOOST_CHECK(T(10) == s.at(0));
+ s.at(1) = T(20);
+ BOOST_CHECK(T(20) == s[1]);
+ BOOST_CHECK(T(20) == s.at(1));
+ }
+}
+
+template <typename T, size_t N>
+void test_resize_nd(size_t n, T const& v)
+{
+ static_vector<T, N> s;
+
+ s.resize(n, v);
+ BOOST_CHECK(s.size() == n);
+ BOOST_CHECK(s.capacity() == N);
+ BOOST_CHECK_THROW( s.at(n), std::out_of_range );
+ if ( 1 < n )
+ {
+ BOOST_CHECK(v == s[0]);
+ BOOST_CHECK(v == s.at(0));
+ BOOST_CHECK(v == s[1]);
+ BOOST_CHECK(v == s.at(1));
+ s[0] = T(10);
+ BOOST_CHECK(T(10) == s[0]);
+ BOOST_CHECK(T(10) == s.at(0));
+ s.at(1) = T(20);
+ BOOST_CHECK(T(20) == s[1]);
+ BOOST_CHECK(T(20) == s.at(1));
+ }
+}
+
+template <typename T, size_t N>
+void test_push_back_nd()
+{
+ static_vector<T, N> s;
+
+ BOOST_CHECK(s.size() == 0);
+ BOOST_CHECK_THROW( s.at(0), std::out_of_range );
+
+ for ( size_t i = 0 ; i < N ; ++i )
+ {
+ s.push_back(T(i));
+ BOOST_CHECK(s.size() == i + 1);
+ BOOST_CHECK_THROW( s.at(i + 1), std::out_of_range );
+ BOOST_CHECK(T(i) == s.at(i));
+ BOOST_CHECK(T(i) == s[i]);
+ BOOST_CHECK(T(i) == s.back());
+ BOOST_CHECK(T(0) == s.front());
+ }
+}
+
+template <typename T, size_t N>
+void test_pop_back_nd()
+{
+ static_vector<T, N> s;
+
+ for ( size_t i = 0 ; i < N ; ++i )
+ s.push_back(T(i));
+
+ for ( size_t i = N ; i > 1 ; --i )
+ {
+ s.pop_back();
+ BOOST_CHECK(s.size() == i - 1);
+ BOOST_CHECK_THROW( s.at(i - 1), std::out_of_range );
+ BOOST_CHECK(T(i - 2) == s.at(i - 2));
+ BOOST_CHECK(T(i - 2) == s[i - 2]);
+ BOOST_CHECK(T(i - 2) == s.back());
+ BOOST_CHECK(T(0) == s.front());
+ }
+}
+
+template <typename It1, typename It2>
+void test_compare_ranges(It1 first1, It1 last1, It2 first2, It2 last2)
+{
+ BOOST_CHECK(std::distance(first1, last1) == std::distance(first2, last2));
+ for ( ; first1 != last1 && first2 != last2 ; ++first1, ++first2 )
+ BOOST_CHECK(*first1 == *first2);
+}
+
+template <typename T, size_t N>
+void test_copy_and_assign_nd(T const& val)
+{
+ static_vector<T, N> s;
+ std::vector<T> v;
+ std::list<T> l;
+
+ for ( size_t i = 0 ; i < N ; ++i )
+ {
+ s.push_back(T(i));
+ v.push_back(T(i));
+ l.push_back(T(i));
+ }
+ // copy ctor
+ {
+ static_vector<T, N> s1(s);
+ BOOST_CHECK(s.size() == s1.size());
+ test_compare_ranges(s.begin(), s.end(), s1.begin(), s1.end());
+ }
+ // copy assignment
+ {
+ static_vector<T, N> s1;
+ BOOST_CHECK(0 == s1.size());
+ s1 = s;
+ BOOST_CHECK(s.size() == s1.size());
+ test_compare_ranges(s.begin(), s.end(), s1.begin(), s1.end());
+ }
+ // ctor(Iter, Iter)
+ {
+ static_vector<T, N> s1(s.begin(), s.end());
+ BOOST_CHECK(s.size() == s1.size());
+ test_compare_ranges(s.begin(), s.end(), s1.begin(), s1.end());
+ }
+ {
+ static_vector<T, N> s1(v.begin(), v.end());
+ BOOST_CHECK(v.size() == s1.size());
+ test_compare_ranges(v.begin(), v.end(), s1.begin(), s1.end());
+ }
+ {
+ static_vector<T, N> s1(l.begin(), l.end());
+ BOOST_CHECK(l.size() == s1.size());
+ test_compare_ranges(l.begin(), l.end(), s1.begin(), s1.end());
+ }
+ // assign(Iter, Iter)
+ {
+ static_vector<T, N> s1;
+ BOOST_CHECK(0 == s1.size());
+ s1.assign(s.begin(), s.end());
+ BOOST_CHECK(s.size() == s1.size());
+ test_compare_ranges(s.begin(), s.end(), s1.begin(), s1.end());
+ }
+ {
+ static_vector<T, N> s1;
+ BOOST_CHECK(0 == s1.size());
+ s1.assign(v.begin(), v.end());
+ BOOST_CHECK(v.size() == s1.size());
+ test_compare_ranges(v.begin(), v.end(), s1.begin(), s1.end());
+ }
+ {
+ static_vector<T, N> s1;
+ BOOST_CHECK(0 == s1.size());
+ s1.assign(l.begin(), l.end());
+ BOOST_CHECK(l.size() == s1.size());
+ test_compare_ranges(l.begin(), l.end(), s1.begin(), s1.end());
+ }
+ // assign(N, V)
+ {
+ static_vector<T, N> s1(s);
+ test_compare_ranges(s.begin(), s.end(), s1.begin(), s1.end());
+ std::vector<T> a(N, val);
+ s1.assign(N, val);
+ test_compare_ranges(a.begin(), a.end(), s1.begin(), s1.end());
+ }
+}
+
+template <typename T, size_t N>
+void test_iterators_nd()
+{
+ static_vector<T, N> s;
+ std::vector<T> v;
+
+ for ( size_t i = 0 ; i < N ; ++i )
+ {
+ s.push_back(T(i));
+ v.push_back(T(i));
+ }
+
+ test_compare_ranges(s.begin(), s.end(), v.begin(), v.end());
+ test_compare_ranges(s.rbegin(), s.rend(), v.rbegin(), v.rend());
+
+ s.assign(v.rbegin(), v.rend());
+
+ test_compare_ranges(s.begin(), s.end(), v.rbegin(), v.rend());
+ test_compare_ranges(s.rbegin(), s.rend(), v.begin(), v.end());
+}
+
+template <typename T, size_t N>
+void test_erase_nd()
+{
+ static_vector<T, N> s;
+
+ for ( size_t i = 0 ; i < N ; ++i )
+ s.push_back(T(i));
+
+ // erase(pos)
+ {
+ for ( size_t i = 0 ; i < N ; ++i )
+ {
+ static_vector<T, N> s1(s);
+ s1.erase(s1.begin() + i);
+ BOOST_CHECK(s1.size() == N - 1);
+ for ( size_t j = 0 ; j < i ; ++j )
+ BOOST_CHECK(s1[j] == T(j));
+ for ( size_t j = i+1 ; j < N ; ++j )
+ BOOST_CHECK(s1[j-1] == T(j));
+ }
+ }
+ // erase(first, last)
+ {
+ size_t n = N/3;
+ for ( size_t i = 0 ; i <= N ; ++i )
+ {
+ static_vector<T, N> s1(s);
+ size_t removed = i + n < N ? n : N - i;
+ s1.erase(s1.begin() + i, s1.begin() + i + removed);
+ BOOST_CHECK(s1.size() == N - removed);
+ for ( size_t j = 0 ; j < i ; ++j )
+ BOOST_CHECK(s1[j] == T(j));
+ for ( size_t j = i+n ; j < N ; ++j )
+ BOOST_CHECK(s1[j-n] == T(j));
+ }
+ }
+}
+
+template <typename T, size_t N>
+void test_insert_nd(T const& val)
+{
+ size_t h = N/2;
+
+ static_vector<T, N> s, ss;
+ std::vector<T> v;
+ std::list<T> l;
+
+ for ( size_t i = 0 ; i < h ; ++i )
+ {
+ s.push_back(T(i));
+ ss.push_back(T(100 + i));
+ v.push_back(T(100 + i));
+ l.push_back(T(100 + i));
+ }
+
+ // insert(pos, val)
+ {
+ for ( size_t i = 0 ; i <= h ; ++i )
+ {
+ static_vector<T, N> s1(s);
+ s1.insert(s1.begin() + i, val);
+ BOOST_CHECK(s1.size() == h+1);
+ for ( size_t j = 0 ; j < i ; ++j )
+ BOOST_CHECK(s1[j] == T(j));
+ BOOST_CHECK(s1[i] == val);
+ for ( size_t j = 0 ; j < h-i ; ++j )
+ BOOST_CHECK(s1[j+i+1] == T(j+i));
+ }
+ }
+ // insert(pos, n, val)
+ {
+ size_t n = size_t(h/1.5f);
+ for ( size_t i = 0 ; i <= h ; ++i )
+ {
+ static_vector<T, N> s1(s);
+ s1.insert(s1.begin() + i, n, val);
+ BOOST_CHECK(s1.size() == h+n);
+ for ( size_t j = 0 ; j < i ; ++j )
+ BOOST_CHECK(s1[j] == T(j));
+ for ( size_t j = 0 ; j < n ; ++j )
+ BOOST_CHECK(s1[j+i] == val);
+ for ( size_t j = 0 ; j < h-i ; ++j )
+ BOOST_CHECK(s1[j+i+n] == T(j+i));
+ }
+ }
+ // insert(pos, first, last)
+ {
+ size_t n = size_t(h/1.5f);
+ for ( size_t i = 0 ; i <= h ; ++i )
+ {
+ static_vector<T, N> s1(s);
+ s1.insert(s1.begin() + i, ss.begin(), ss.begin() + n);
+ BOOST_CHECK(s1.size() == h+n);
+ for ( size_t j = 0 ; j < i ; ++j )
+ BOOST_CHECK(s1[j] == T(j));
+ for ( size_t j = 0 ; j < n ; ++j )
+ BOOST_CHECK(s1[j+i] == T(100 + j));
+ for ( size_t j = 0 ; j < h-i ; ++j )
+ BOOST_CHECK(s1[j+i+n] == T(j+i));
+ }
+ }
+ {
+ size_t n = size_t(h/1.5f);
+ for ( size_t i = 0 ; i <= h ; ++i )
+ {
+ static_vector<T, N> s1(s);
+ s1.insert(s1.begin() + i, v.begin(), v.begin() + n);
+ BOOST_CHECK(s1.size() == h+n);
+ for ( size_t j = 0 ; j < i ; ++j )
+ BOOST_CHECK(s1[j] == T(j));
+ for ( size_t j = 0 ; j < n ; ++j )
+ BOOST_CHECK(s1[j+i] == T(100 + j));
+ for ( size_t j = 0 ; j < h-i ; ++j )
+ BOOST_CHECK(s1[j+i+n] == T(j+i));
+ }
+ }
+ {
+ size_t n = size_t(h/1.5f);
+ for ( size_t i = 0 ; i <= h ; ++i )
+ {
+ static_vector<T, N> s1(s);
+ typename std::list<T>::iterator it = l.begin();
+ std::advance(it, n);
+ s1.insert(s1.begin() + i, l.begin(), it);
+ BOOST_CHECK(s1.size() == h+n);
+ for ( size_t j = 0 ; j < i ; ++j )
+ BOOST_CHECK(s1[j] == T(j));
+ for ( size_t j = 0 ; j < n ; ++j )
+ BOOST_CHECK(s1[j+i] == T(100 + j));
+ for ( size_t j = 0 ; j < h-i ; ++j )
+ BOOST_CHECK(s1[j+i+n] == T(j+i));
+ }
+ }
+}
+
+template <typename T>
+void test_capacity_0_nd()
+{
+ static_vector<T, 10> v(5u, T(0));
+
+ static_vector<T, 0> s;
+ BOOST_CHECK(s.size() == 0);
+ BOOST_CHECK(s.capacity() == 0);
+ BOOST_CHECK_THROW(s.at(0), std::out_of_range);
+ BOOST_CHECK_THROW(s.resize(5u, T(0)), std::bad_alloc);
+ BOOST_CHECK_THROW(s.push_back(T(0)), std::bad_alloc);
+ BOOST_CHECK_THROW(s.insert(s.end(), T(0)), std::bad_alloc);
+ BOOST_CHECK_THROW(s.insert(s.end(), 5u, T(0)), std::bad_alloc);
+ BOOST_CHECK_THROW(s.insert(s.end(), v.begin(), v.end()), std::bad_alloc);
+ BOOST_CHECK_THROW(s.assign(v.begin(), v.end()), std::bad_alloc);
+ BOOST_CHECK_THROW(s.assign(5u, T(0)), std::bad_alloc);
+ try{
+ static_vector<T, 0> s2(v.begin(), v.end());
+ BOOST_CHECK(false);
+ }catch(std::bad_alloc &){}
+ try{
+ static_vector<T, 0> s1(5u, T(0));
+ BOOST_CHECK(false);
+ }catch(std::bad_alloc &){}
+}
+
+template <typename T, size_t N>
+void test_exceptions_nd()
+{
+ static_vector<T, N> v(N, T(0));
+ static_vector<T, N/2> s(N/2, T(0));
+
+ BOOST_CHECK_THROW(s.resize(N, T(0)), std::bad_alloc);
+ BOOST_CHECK_THROW(s.push_back(T(0)), std::bad_alloc);
+ BOOST_CHECK_THROW(s.insert(s.end(), T(0)), std::bad_alloc);
+ BOOST_CHECK_THROW(s.insert(s.end(), N, T(0)), std::bad_alloc);
+ BOOST_CHECK_THROW(s.insert(s.end(), v.begin(), v.end()), std::bad_alloc);
+ BOOST_CHECK_THROW(s.assign(v.begin(), v.end()), std::bad_alloc);
+ BOOST_CHECK_THROW(s.assign(N, T(0)), std::bad_alloc);
+ try{
+ static_vector<T, N/2> s2(v.begin(), v.end());
+ BOOST_CHECK(false);
+ }catch(std::bad_alloc &){}
+ try{
+ static_vector<T, N/2> s1(N, T(0));
+ BOOST_CHECK(false);
+ }catch(std::bad_alloc &){}
+}
+
+int test_main(int, char* [])
+{
+ BOOST_CHECK(counting_value::count() == 0);
+
+ test_ctor_ndc<int, 10>();
+ test_ctor_ndc<value_ndc, 10>();
+ test_ctor_ndc<counting_value, 10>();
+ BOOST_CHECK(counting_value::count() == 0);
+
+ test_ctor_nc<int, 10>(5);
+ test_ctor_nc<value_nc, 10>(5);
+ test_ctor_nc<counting_value, 10>(5);
+ BOOST_CHECK(counting_value::count() == 0);
+
+ test_ctor_nd<int, 10>(5, 1);
+ test_ctor_nd<value_nd, 10>(5, value_nd(1));
+ test_ctor_nd<counting_value, 10>(5, counting_value(1));
+ BOOST_CHECK(counting_value::count() == 0);
+
+ test_resize_nc<int, 10>(5);
+ test_resize_nc<value_nc, 10>(5);
+ test_resize_nc<counting_value, 10>(5);
+ BOOST_CHECK(counting_value::count() == 0);
+
+ test_resize_nd<int, 10>(5, 1);
+ test_resize_nd<value_nd, 10>(5, value_nd(1));
+ test_resize_nd<counting_value, 10>(5, counting_value(1));
+ BOOST_CHECK(counting_value::count() == 0);
+
+ test_push_back_nd<int, 10>();
+ test_push_back_nd<value_nd, 10>();
+ test_push_back_nd<counting_value, 10>();
+ BOOST_CHECK(counting_value::count() == 0);
+
+ test_pop_back_nd<int, 10>();
+ test_pop_back_nd<value_nd, 10>();
+ test_pop_back_nd<counting_value, 10>();
+ BOOST_CHECK(counting_value::count() == 0);
+
+ test_copy_and_assign_nd<int, 10>(1);
+ test_copy_and_assign_nd<value_nd, 10>(value_nd(1));
+ test_copy_and_assign_nd<counting_value, 10>(counting_value(1));
+ BOOST_CHECK(counting_value::count() == 0);
+
+ test_iterators_nd<int, 10>();
+ test_iterators_nd<value_nd, 10>();
+ test_iterators_nd<counting_value, 10>();
+ BOOST_CHECK(counting_value::count() == 0);
+
+ test_erase_nd<int, 10>();
+ test_erase_nd<value_nd, 10>();
+ test_erase_nd<counting_value, 10>();
+ BOOST_CHECK(counting_value::count() == 0);
+
+ test_insert_nd<int, 10>(50);
+ test_insert_nd<value_nd, 10>(value_nd(50));
+ test_insert_nd<counting_value, 10>(counting_value(50));
+ BOOST_CHECK(counting_value::count() == 0);
+
+ test_capacity_0_nd<int>();
+ test_capacity_0_nd<value_nd>();
+ test_capacity_0_nd<counting_value>();
+ BOOST_CHECK(counting_value::count() == 0);
+
+ test_exceptions_nd<int, 10>();
+ test_exceptions_nd<value_nd, 10>();
+ test_exceptions_nd<counting_value, 10>();
+ BOOST_CHECK(counting_value::count() == 0);
+
+ return 0;
+}


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk