|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r81971 - in sandbox-branches/geometry/index: boost/geometry/extensions/index test
From: adam.wulkiewicz_at_[hidden]
Date: 2012-12-15 11:30:58
Author: awulkiew
Date: 2012-12-15 11:30:57 EST (Sat, 15 Dec 2012)
New Revision: 81971
URL: http://svn.boost.org/trac/boost/changeset/81971
Log:
Added ctor and modified assign to static_vector.
static_vector(Iter, Iter), assign(Iter, Iter) + separated version for RandomIterators.
Private helper methods now are able to take arbitrary type (Iterator, Value).
Text files modified:
sandbox-branches/geometry/index/boost/geometry/extensions/index/static_vector.hpp | 304 ++++++++++++++++++++++++++++-----------
sandbox-branches/geometry/index/test/static_vector.cpp | 59 ++++++-
2 files changed, 265 insertions(+), 98 deletions(-)
Modified: sandbox-branches/geometry/index/boost/geometry/extensions/index/static_vector.hpp
==============================================================================
--- sandbox-branches/geometry/index/boost/geometry/extensions/index/static_vector.hpp (original)
+++ sandbox-branches/geometry/index/boost/geometry/extensions/index/static_vector.hpp 2012-12-15 11:30:57 EST (Sat, 15 Dec 2012)
@@ -7,10 +7,16 @@
// http://www.boost.org/LICENSE_1_0.txt)
#include <stdexcept>
-#include <boost/mpl/assert.hpp>
+
#include <boost/aligned_storage.hpp>
#include <boost/iterator/reverse_iterator.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>
@@ -55,32 +61,38 @@
explicit static_vector(size_type s)
: m_size(0)
{
- resize(s); // may throw
+ resize(s); // may throw
}
// strong
static_vector(size_type s, value_type const& value)
: m_size(0)
{
- resize(s, value); // may throw
+ resize(s, value); // may throw
}
// strong
static_vector(static_vector const& other)
+ : m_size(other.m_size)
{
- //BOOST_ASSERT_MSG(other.m_size <= Capacity, "capacity too small");
+ //BOOST_ASSERT_MSG(other.m_size <= Capacity, "size can't exceed the capacity");
+ //if ( Capacity <= other.m_size ) throw std::bad_alloc();
+
+ this->uninitialized_copy(other.begin(), other.end(), this->begin()); // may throw
+ }
- this->uninitialized_copy(other.ptr(0), other.ptr(other.m_size), this->ptr(0),
- boost::has_trivial_copy<value_type>());
- m_size = other.m_size;
+ // strong
+ template <typename Iterator>
+ static_vector(Iterator first, Iterator last)
+ : m_size(0)
+ {
+ assign(first, last); // may throw
}
// basic
static_vector & operator=(static_vector const& other)
{
- //BOOST_ASSERT_MSG(other.m_size <= Capacity, "capacity too small");
-
- assign(other.ptr(0), other.ptr(other.m_size));
+ assign(other.begin(), other.end()); // may throw
return *this;
}
@@ -88,8 +100,7 @@
// nothrow
~static_vector()
{
- this->destroy(this->ptr(0), this->ptr(m_size),
- boost::has_trivial_destructor<value_type>());
+ this->destroy(this->begin(), this->end());
}
// strong
@@ -97,17 +108,15 @@
{
if ( s < m_size )
{
- this->destroy(this->ptr(s), this->ptr(m_size),
- boost::has_trivial_destructor<value_type>());
- m_size = s;
+ this->destroy(this->begin() + s, this->end());
}
else
{
BOOST_ASSERT_MSG(s <= Capacity, "size can't exceed the capacity");
- this->construct(this->ptr(m_size), this->ptr(s),
- boost::has_trivial_constructor<value_type>()); // may throw
- m_size = s;
+ //if ( Capacity <= s ) throw std::bad_alloc();
+ this->construct(this->ptr(m_size), this->ptr(s)); // may throw
}
+ m_size = s; // update end
}
// strong
@@ -115,74 +124,55 @@
{
if ( s < m_size )
{
- this->destroy(this->ptr(s), this->ptr(m_size),
- boost::has_trivial_destructor<value_type>());
- m_size = s;
+ this->destroy(this->begin() + s, this->end());
}
else
{
BOOST_ASSERT_MSG(s <= Capacity, "size can't exceed the capacity");
- std::uninitialized_fill(this->ptr(m_size), this->ptr(s), value); // may throw
- m_size = s;
+ //if ( Capacity <= s ) throw std::bad_alloc();
+ std::uninitialized_fill(this->ptr(m_size), this->ptr(s), value); // may throw
}
+ m_size = s; // update end
}
// nothrow
void reserve(size_type BOOST_GEOMETRY_INDEX_ASSERT_UNUSED_PARAM(s))
{
- BOOST_ASSERT_MSG(s <= Capacity, "max capacity reached");
+ BOOST_ASSERT_MSG(s <= Capacity, "size can't exceed the capacity");
+ //if ( Capacity <= s ) throw std::bad_alloc();
}
// strong
+ //template <typename Value>
void push_back(Value const& value)
{
- BOOST_ASSERT_MSG(m_size < Capacity, "max capacity reached");
- this->uninitialized_copy(this->ptr(m_size), value,
- boost::has_trivial_copy<value_type>()); // may throw
- ++m_size;
+ BOOST_ASSERT_MSG(m_size < Capacity, "size can't exceed the capacity");
+ //if ( Capacity <= m_size ) throw std::bad_alloc();
+ this->uninitialized_copy(value, this->end()); // may throw
+ ++m_size; // update end
}
// nothrow
void pop_back()
{
BOOST_ASSERT_MSG(0 < m_size, "the container is empty");
- --m_size;
- this->destroy(this->ptr(m_size), boost::has_trivial_destructor<value_type>());
+ --m_size; // update end
+ this->destroy(this->ptr(m_size));
}
// basic
- void assign(const value_type * first, const value_type * last)
+ template <typename Iterator>
+ void assign(Iterator first, Iterator last)
{
- size_type s = std::distance(first, last);
-
- BOOST_ASSERT_MSG(s <= Capacity, "max capacity reached");
-
- if ( m_size <= s )
- {
- this->copy(first, first + m_size, this->ptr(0),
- boost::has_trivial_assign<value_type>()); // may throw
-
- this->uninitialized_copy(first + m_size, last, this->ptr(m_size),
- boost::has_trivial_copy<value_type>()); // may throw
- m_size = s;
- }
- else
- {
- this->copy(first, last, this->ptr(0),
- boost::has_trivial_assign<value_type>()); // may throw
-
- this->destroy(this->ptr(s), this->ptr(m_size),
- boost::has_trivial_destructor<value_type>());
- m_size = s;
- }
+ typedef typename boost::iterator_traversal<Iterator>::type traversal;
+ assign_dispatch(first, last, traversal()); // may throw
}
// nothrow
void clear()
{
- this->destroy(this->ptr(0), this->ptr(m_size),
- boost::has_trivial_destructor<value_type>());
- m_size = 0;
+ this->destroy(this->ptr(0), this->ptr(m_size));
+ m_size = 0; // update end
}
// strong
@@ -219,28 +209,28 @@
Value & front()
{
BOOST_ASSERT_MSG(0 < m_size, "the container is empty");
- return *(this->ptr(0));
+ return *(this->begin());
}
// nothrow
Value const& front() const
{
BOOST_ASSERT_MSG(0 < m_size, "the container is empty");
- return *(this->ptr(0));
+ return *(this->begin());
}
// nothrow
Value & back()
{
BOOST_ASSERT_MSG(0 < m_size, "the container is empty");
- return *(this->ptr(m_size - 1));
+ return *(this->end() - 1);
}
// nothrow
Value const& back() const
{
BOOST_ASSERT_MSG(0 < m_size, "the container is empty");
- return *(this->ptr(m_size - 1));
+ return *(this->end() - 1);
}
// nothrow
@@ -248,9 +238,9 @@
const Value * data() const { return this->ptr(0); }
// nothrow
- iterator begin() { return this->ptr(0); }
- const_iterator begin() const { return this->ptr(0); }
- const_iterator cbegin() const { return this->ptr(0); }
+ iterator begin() { return this->ptr(); }
+ const_iterator begin() const { return this->ptr(); }
+ const_iterator cbegin() const { return this->ptr(); }
iterator end() { return this->ptr(m_size); }
const_iterator end() const { return this->ptr(m_size); }
const_iterator cend() const { return this->ptr(m_size); }
@@ -269,78 +259,202 @@
bool empty() const { return 0 == m_size; }
private:
- void copy(const value_type * first, const value_type * last, value_type * dst,
- boost::true_type const& /*has_trivial_assign*/)
+
+ // assign
+
+ template <typename Iterator>
+ void assign_dispatch(Iterator first, Iterator last, boost::random_access_traversal_tag const&)
+ {
+ size_type s = std::distance(first, last);
+
+ BOOST_ASSERT_MSG(s <= Capacity, "size can't exceed the capacity");
+ //if ( Capacity <= m_size ) throw std::bad_alloc();
+
+ if ( m_size <= s )
+ {
+ this->copy(first, first + m_size, this->begin()); // may throw
+ this->uninitialized_copy(first + m_size, last, this->ptr(m_size)); // may throw
+ }
+ else
+ {
+ this->copy(first, last, this->begin()); // may throw
+ this->destroy(this->ptr(s), this->ptr(m_size));
+ }
+ m_size = s; // update end
+ }
+
+ template <typename Iterator, typename Traversal>
+ void assign_dispatch(Iterator first, Iterator last, Traversal const& /*not_random_access*/)
+ {
+ size_t s = 0;
+ iterator it = this->begin();
+
+ for ( ; it != this->end() && first != last ; ++it, ++first, ++s )
+ *it = *first; // may throw
+
+ this->destroy(it, this->end());
+
+ try
+ {
+ for ( ; first != last ; ++it, ++first, ++s )
+ this->uninitialized_copy(*first, it); // may throw
+ m_size = s; // update end
+ }
+ catch(...)
+ {
+ this->destroy(this->begin() + m_size, it);
+ throw;
+ }
+ }
+
+ // 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));
}
- void copy(const value_type * first, const value_type * last, value_type * dst,
- boost::false_type const& /*has_trivial_assign*/)
+ 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)
{
- std::copy(first, last, dst); // may throw
+ 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(const value_type * first, const value_type * last, value_type * dst,
- boost::true_type const& /*has_trivial_copy*/)
+ 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));
}
- void uninitialized_copy(const value_type * first, const value_type * last, value_type * dst,
- boost::false_type const& /*has_trivial_copy*/)
+ 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_copy
+
+ template <typename Value>
+ void uninitialized_copy(Value const& v, iterator dst)
{
- std::uninitialized_copy(first, last, dst); // may throw
+ typedef typename
+ mpl::and_<
+ has_trivial_copy<value_type>,
+ is_same<Value, value_type>
+ >::type
+ use_memcpy;
+
+ uninitialized_copy_dispatch(v, dst, use_memcpy()); // may throw
}
- void uninitialized_copy(value_type * ptr, value_type const& v,
- boost::true_type const& /*has_trivial_copy*/)
+ void uninitialized_copy_dispatch(value_type const& v, value_type * ptr,
+ boost::mpl::bool_<true> const& /*use_memcpy*/)
{
::memcpy(ptr, &v, sizeof(value_type));
}
- void uninitialized_copy(value_type * ptr, value_type const& v,
- boost::false_type const& /*has_trivial_copy*/)
+ template <typename Value>
+ void uninitialized_copy_dispatch(Value const& v, value_type * ptr,
+ boost::mpl::bool_<false> const& /*use_memcpy*/)
{
new (ptr) value_type(v); // may throw
}
- void destroy(const value_type * /*first*/, const value_type * /*last*/,
- boost::true_type const& /*has_trivial_destructor*/)
+ // 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(const value_type * first, const value_type * last,
- boost::false_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();
}
- void destroy(const value_type * /*ptr*/,
- boost::true_type const& /*has_trivial_destructor*/)
+ // 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(const value_type * ptr, boost::false_type const& /*has_trivial_destructor*/)
+ void destroy_dispatch(value_type * ptr,
+ boost::false_type const& /*has_trivial_destructor*/)
{
ptr->~value_type();
}
- void construct(value_type * /*first*/, value_type * /*last*/,
- boost::true_type const& /*has_trivial_constructor*/)
+ // 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(value_type * first, value_type * last,
- boost::false_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
+ new (it) value_type(); // may throw
}
catch(...)
{
- this->destroy(first, it, boost::has_trivial_destructor<value_type>());
+ this->destroy(first, it);
throw;
}
}
@@ -355,6 +469,16 @@
return (reinterpret_cast<const Value*>(m_storage.address()) + i);
}
+ 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;
size_type m_size;
};
Modified: sandbox-branches/geometry/index/test/static_vector.cpp
==============================================================================
--- sandbox-branches/geometry/index/test/static_vector.cpp (original)
+++ sandbox-branches/geometry/index/test/static_vector.cpp 2012-12-15 11:30:57 EST (Sat, 15 Dec 2012)
@@ -195,35 +195,78 @@
}
}
+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()
{
static_vector<T, N> s;
+ std::vector<T> v;
+ std::list<T> l;
for ( size_t i = 0 ; i < N ; ++i )
- s.push_back(i);
-
+ {
+ s.push_back(i);
+ v.push_back(i);
+ l.push_back(i);
+ }
+ // copy ctor
{
static_vector<T, N> s1(s);
BOOST_CHECK(s.size() == s1.size());
- for ( size_t i = 0 ; i < N ; ++i )
- BOOST_CHECK(s[i] == s1[i]) ;
+ 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());
- for ( size_t i = 0 ; i < N ; ++i )
- BOOST_CHECK(s[i] == s1[i]) ;
+ 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());
- for ( size_t i = 0 ; i < N ; ++i )
- BOOST_CHECK(s[i] == s1[i]) ;
+ 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());
}
}
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