Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r82219 - in sandbox/static_vector: boost/container boost/container/detail test
From: adam.wulkiewicz_at_[hidden]
Date: 2012-12-27 13:18:48


Author: awulkiew
Date: 2012-12-27 13:18:47 EST (Thu, 27 Dec 2012)
New Revision: 82219
URL: http://svn.boost.org/trac/boost/changeset/82219

Log:
Added emplace_back().
Text files modified:
   sandbox/static_vector/boost/container/detail/static_vector_util.hpp | 141 +++++++++++++++++++++++++++------------
   sandbox/static_vector/boost/container/static_vector.hpp | 65 +++++++++---------
   sandbox/static_vector/test/static_vector.cpp | 53 ++++++++++----
   3 files changed, 166 insertions(+), 93 deletions(-)

Modified: sandbox/static_vector/boost/container/detail/static_vector_util.hpp
==============================================================================
--- sandbox/static_vector/boost/container/detail/static_vector_util.hpp (original)
+++ sandbox/static_vector/boost/container/detail/static_vector_util.hpp 2012-12-27 13:18:47 EST (Thu, 27 Dec 2012)
@@ -12,6 +12,9 @@
 #ifndef BOOST_CONTAINER_DETAIL_STATIC_VECTOR_UTIL_HPP
 #define BOOST_CONTAINER_DETAIL_STATIC_VECTOR_UTIL_HPP
 
+#include <boost/container/detail/workaround.hpp>
+#include <boost/container/detail/preprocessor.hpp>
+
 #include <cstddef>
 #include <cstring>
 #include <memory>
@@ -261,35 +264,6 @@
     return uninitialized_copy_dispatch(first, last, dst, use_memcpy()); // may throw
 }
 
-// uninitialized_fill(I, V)
-
-template <typename I, typename V>
-void uninitialized_fill_dispatch(I pos, V const& v,
- boost::mpl::bool_<true> const& /*use_memcpy*/)
-{
- ::memcpy(boost::addressof(*pos), boost::addressof(v), sizeof(V));
-}
-
-template <typename I, typename V>
-void uninitialized_fill_dispatch(I pos, V const& v,
- boost::mpl::bool_<false> const& /*use_memcpy*/)
-{
- new (static_cast<void*>(boost::addressof(*pos))) V(v); // may throw
-}
-
-template <typename I, typename V>
-void uninitialized_fill(I dst, V const& v)
-{
- typedef typename
- ::boost::mpl::and_<
- is_corresponding_value<I, V>,
- ::boost::has_trivial_copy<V>
- >::type
- use_memcpy;
-
- uninitialized_fill_dispatch(dst, v, use_memcpy()); // may throw
-}
-
 // uninitialized_move(I, I, O)
 
 template <typename I, typename O>
@@ -446,16 +420,16 @@
     fill_dispatch(pos, v, use_memcpy()); // may throw
 }
 
-// construct
+// uninitialized_fill(I, I)
 
 template <typename I>
-void construct_dispatch(I /*first*/, I /*last*/,
- boost::true_type const& /*has_trivial_constructor*/)
+void uninitialized_fill_dispatch(I /*first*/, I /*last*/,
+ boost::true_type const& /*has_trivial_constructor*/)
 {}
 
 template <typename I>
-void construct_dispatch(I first, I last,
- boost::false_type const& /*has_trivial_constructor*/)
+void uninitialized_fill_dispatch(I first, I last,
+ boost::false_type const& /*has_trivial_constructor*/)
 {
     typedef typename boost::iterator_value<I>::type value_type;
     I it = first;
@@ -474,12 +448,91 @@
 }
 
 template <typename I>
-void construct(I first, I last)
+void uninitialized_fill(I first, I last)
 {
     typedef typename boost::iterator_value<I>::type value_type;
- construct_dispatch(first, last, has_trivial_constructor<value_type>()); // may throw
+ uninitialized_fill_dispatch(first, last, has_trivial_constructor<value_type>()); // may throw
 }
 
+// construct(I, V)
+
+template <typename I, typename V>
+void construct_dispatch(I pos, V const& v,
+ boost::mpl::bool_<true> const& /*use_memcpy*/)
+{
+ ::memcpy(boost::addressof(*pos), boost::addressof(v), sizeof(V));
+}
+
+template <typename I, typename P>
+void construct_dispatch(I pos, P const& p,
+ boost::mpl::bool_<false> const& /*use_memcpy*/)
+{
+ typedef typename boost::iterator_value<I>::type V;
+ new (static_cast<void*>(boost::addressof(*pos))) V(p); // may throw
+}
+
+
+// P may be e.g. V, const V, boost::rv<V>, const boost::rv<V>
+
+template <typename I, typename P>
+void construct(I pos, P const& p)
+{
+ typedef typename
+ ::boost::mpl::and_<
+ is_corresponding_value<I, P>,
+ ::boost::has_trivial_copy<P>
+ >::type
+ use_memcpy;
+
+ construct_dispatch(pos, p, use_memcpy()); // may throw
+}
+
+template <typename I, typename P>
+void construct(I pos, BOOST_RV_REF(P) p)
+{
+ typedef typename
+ ::boost::mpl::and_<
+ is_corresponding_value<I, P>,
+ ::boost::has_trivial_copy<P>
+ >::type
+ use_memcpy;
+
+ typedef typename boost::iterator_value<I>::type V;
+ new (static_cast<void*>(boost::addressof(*pos))) V(p); // may throw
+}
+
+#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+
+template <typename I, class ...Args>
+void construct(I pos, BOOST_FWD_REF(Args) ...args)
+{
+ typedef typename boost::iterator_value<I>::type V;
+ new (static_cast<void*>(boost::addressof(*pos))) V(::boost::forward<Args>(args)...); // may throw
+}
+
+#else // !BOOST_NO_VARIADIC_TEMPLATES
+
+// BOOST_NO_RVALUE_REFERENCES -> P0 const& p0
+// !BOOST_NO_RVALUE_REFERENCES -> P0 && p0
+// which means that version with one parameter may take V const& v
+
+#define BOOST_PP_LOCAL_MACRO(n) \
+template <typename I, typename P BOOST_PP_ENUM_TRAILING_PARAMS(n, typename P) > \
+void construct(I pos, \
+ BOOST_CONTAINER_PP_PARAM(P, p) \
+ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+{ \
+ typedef typename boost::iterator_value<I>::type V; \
+ new \
+ (static_cast<void*>(boost::addressof(*pos))) \
+ V(p, BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); /*may throw*/ \
+} \
+//
+#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
+#include BOOST_PP_LOCAL_ITERATE()
+
+#endif
+
 #else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 
 template <typename I, typename O>
@@ -494,12 +547,6 @@
     return std::uninitialized_copy(first, last, dst); // may throw
 }
 
-template <typename I, typename V>
-inline void uninitialized_fill(I pos, V const& v)
-{
- new (static_cast<void*>(boost::addressof(*pos))) V(v); // may throw
-}
-
 template <typename I, typename O>
 inline O move(I first, I last, O dst)
 {
@@ -534,7 +581,7 @@
 }
 
 template <typename I>
-void construct(I first, I last)
+void construct_default(I first, I last)
 {
     typedef typename boost::iterator_value<I>::type value_type;
     I it = first;
@@ -552,6 +599,12 @@
     BOOST_CATCH_END
 }
 
+template <typename I, typename V>
+inline void construct(I pos, V const& v)
+{
+ new (static_cast<void*>(boost::addressof(*pos))) V(v); // may throw
+}
+
 #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 
 // uninitialized_copy_checked
@@ -569,7 +622,7 @@
             if ( max_count <= count )
                 return (std::numeric_limits<std::size_t>::max)();
 
- uninitialized_fill(it, *first); // may throw
+ construct(it, *first); // may throw
         }
     }
     BOOST_CATCH(...)

Modified: sandbox/static_vector/boost/container/static_vector.hpp
==============================================================================
--- sandbox/static_vector/boost/container/static_vector.hpp (original)
+++ sandbox/static_vector/boost/container/static_vector.hpp 2012-12-27 13:18:47 EST (Thu, 27 Dec 2012)
@@ -12,9 +12,6 @@
 
 #include <boost/container/detail/static_vector_util.hpp>
 
-#include <boost/container/detail/workaround.hpp>
-#include <boost/container/detail/preprocessor.hpp>
-
 #ifndef BOOST_NO_EXCEPTIONS
 #include <stdexcept>
 #endif // BOOST_NO_EXCEPTIONS
@@ -338,7 +335,7 @@
         {
             errh::check_capacity(*this, count); // may throw
 
- sv::construct(this->end(), this->begin() + count); // may throw
+ sv::uninitialized_fill(this->end(), this->begin() + count); // may throw
         }
         m_size = count; // update end
     }
@@ -372,7 +369,7 @@
         errh::check_capacity(*this, m_size + 1); // may throw
         
         namespace sv = static_vector_detail;
- sv::uninitialized_fill(this->end(), value); // may throw
+ sv::construct(this->end(), value); // may throw
         ++m_size; // update end
     }
 
@@ -401,14 +398,16 @@
 
         if ( position == this->end() )
         {
- sv::uninitialized_fill(position, value); // may throw
+ sv::construct(position, value); // may throw
             ++m_size; // update end
         }
         else
         {
             // TODO - should following lines check for exception and revert to the old size?
 
- sv::uninitialized_fill(this->end(), *(this->end() - 1)); // may throw
+ // TODO - should move be used only if it's nonthrowing?
+ value_type & r = *(this->end() - 1);
+ sv::construct(this->end(), boost::move(r)); // may throw
             ++m_size; // update end
             sv::move_backward(position, this->end() - 2, this->end() - 1); // may throw
             sv::fill(position, value); // may throw
@@ -530,34 +529,34 @@
         m_size = count; // update end
     }
 
-//#if defined(BOOST_CONTAINER_PERFECT_FORWARDING)
-// template<class ...Args>
-// void emplace_back(Args &&...args)
-// {
-// errh::check_capacity(*this, m_size + 1); // may throw
-
-// namespace sv = static_vector_detail;
-// sv::uninitialized_fill(this->end(), ::boost::forward<Args>(args)); // may throw
-// ++m_size; // update end
-// }
-
-//#else // BOOST_CONTAINER_PERFECT_FORWARDING
-
-// #define BOOST_PP_LOCAL_MACRO(n) \
-// BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
-// void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
-// { \
-// errh::check_capacity(*this, m_size + 1); /*may throw*/\
-// \
-// namespace sv = static_vector_detail; \
-// sv::uninitialized_fill(this->end() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); /*may throw*/\
-// ++m_size; /*update end*/ \
-// }
+#if defined(BOOST_CONTAINER_PERFECT_FORWARDING)
+ template<class ...Args>
+ void emplace_back(Args &&...args)
+ {
+ errh::check_capacity(*this, m_size + 1); // may throw
+
+ namespace sv = static_vector_detail;
+ sv::construct(this->end(), ::boost::forward<Args>(args)); // may throw
+ ++m_size; // update end
+ }
+
+#else // BOOST_CONTAINER_PERFECT_FORWARDING
 
-// #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
-// #include BOOST_PP_LOCAL_ITERATE()
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { \
+ errh::check_capacity(*this, m_size + 1); /*may throw*/\
+ \
+ namespace sv = static_vector_detail; \
+ sv::construct(this->end() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); /*may throw*/\
+ ++m_size; /*update end*/ \
+ } \
+ //
+ #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
 
-//#endif // BOOST_CONTAINER_PERFECT_FORWARDING
+#endif // BOOST_CONTAINER_PERFECT_FORWARDING
 
     // nothrow
     void clear()

Modified: sandbox/static_vector/test/static_vector.cpp
==============================================================================
--- sandbox/static_vector/test/static_vector.cpp (original)
+++ sandbox/static_vector/test/static_vector.cpp 2012-12-27 13:18:47 EST (Thu, 27 Dec 2012)
@@ -7,6 +7,7 @@
 // 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/container/static_vector.hpp>
 
 #ifdef BOOST_SINGLE_HEADER_UTF
@@ -703,21 +704,34 @@
     }
 }
 
-//template <typename T, size_t N>
-//void test_emplace_2p()
-//{
-// static_vector<T, N, bad_alloc_strategy> v;
-
-// for (int i = 0 ; i < int(N) ; ++i )
-// v.emplace_back(i, 100 + i);
-// BOOST_CHECK(v.size() == N);
-//#ifndef BOOST_NO_EXCEPTIONS
-// BOOST_CHECK_THROW(v.emplace_back(N, 100 + N), std::bad_alloc);
-//#endif
-// BOOST_CHECK(v.size() == N);
-// for (int i = 0 ; i < int(N) ; ++i )
-// BOOST_CHECK(v[i] == T(i, 100 + i));
-//}
+template <typename T, size_t N>
+void test_emplace_2p()
+{
+ static_vector<T, N, bad_alloc_strategy> v;
+
+ for (int i = 0 ; i < int(N) ; ++i )
+ v.emplace_back(i, 100 + i);
+ BOOST_CHECK(v.size() == N);
+#ifndef BOOST_NO_EXCEPTIONS
+ BOOST_CHECK_THROW(v.emplace_back(N, 100 + N), std::bad_alloc);
+#endif
+ BOOST_CHECK(v.size() == N);
+ for (int i = 0 ; i < int(N) ; ++i )
+ BOOST_CHECK(v[i] == T(i, 100 + i));
+}
+
+template <typename T, size_t N>
+void test_sv_elem(T const& t)
+{
+ typedef static_vector<T, N, bad_alloc_strategy> V;
+
+ static_vector<V, N, bad_alloc_strategy> v;
+
+ v.push_back(V(N/2, t));
+ v.push_back(V(N/2, t));
+ v.insert(v.begin(), V(N/2, t));
+ v.insert(v.end(), V(N/2, t));
+}
 
 #ifdef BOOST_SINGLE_HEADER_UTF
 BOOST_AUTO_TEST_CASE(static_vector_test)
@@ -825,7 +839,14 @@
     test_swap_and_move_nd<shptr_value, 10>();
     test_swap_and_move_nd<copy_movable, 10>();
 
- //test_emplace_2p<value_2p, 10>();
+ test_emplace_2p<value_2p, 10>();
+
+ test_sv_elem<int, 10>(50);
+ test_sv_elem<value_nd, 10>(value_nd(50));
+ test_sv_elem<counting_value, 10>(counting_value(50));
+ BOOST_CHECK(counting_value::count() == 0);
+ test_sv_elem<shptr_value, 10>(shptr_value(50));
+ test_sv_elem<copy_movable, 10>(copy_movable(50));
 
 #ifndef BOOST_SINGLE_HEADER_UTF
     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