$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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;