diff --git a/doc/container.qbk b/doc/container.qbk
index 61ef914..06423fc 100644
--- a/doc/container.qbk
+++ b/doc/container.qbk
@@ -1467,7 +1467,7 @@ collect them containers and build [*Boost.Container], a library targeted to a wi
* Fixed bugs/issues:
* [@https://github.com/boostorg/container/issues/334 GitHub #334: ['"Wrong overload resolution protection in implementation of P2363R5"]].
-* Added [memberref boost::container::vector::unchecked_emplace_back unchecked_emplace_back] to [classref boost::container::vector vector],
+* Added `unchecked_emplace_back` and `unchecked_push_back` to [classref boost::container::vector vector],
[classref boost::container::static_vector static_vector] and [classref boost::container::small_vector small_vector].
[endsect]
diff --git a/include/boost/container/static_vector.hpp b/include/boost/container/static_vector.hpp
index 1d9418a..25aba1a 100644
--- a/include/boost/container/static_vector.hpp
+++ b/include/boost/container/static_vector.hpp
@@ -608,7 +608,35 @@ public:
//!
//! @par Complexity
//! Constant O(1).
- void push_back(BOOST_RV_REF(value_type) value);
+ void push_back(value_type &&value);
+
+ //! @pre size() < capacity(). Otherwise, the behavior is undefined.
+ //!
+ //! @brief Adds a copy of value at the end.
+ //!
+ //! @param value The value used to copy construct the new element.
+ //!
+ //! @par Throws
+ //! @li If T's copy constructor throws.
+ //! @li If \c throw_on_overflow option is set and the container runs out of capacity.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ void unchecked_push_back(value_type const& value);
+
+ //! @pre size() < capacity(). Otherwise, the behavior is undefined.
+ //!
+ //! @brief Moves value to the end.
+ //!
+ //! @param value The value to move construct the new element.
+ //!
+ //! @par Throws
+ //! @li If T's move constructor throws.
+ //! @li If \c throw_on_overflow option is set and the container runs out of capacity.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ void unchecked_push_back(value_type &&value);
//! @pre !empty()
//!
diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp
index 99138ac..f5aa457 100644
--- a/include/boost/container/vector.hpp
+++ b/include/boost/container/vector.hpp
@@ -1984,7 +1984,7 @@ private:
//!
//! Note: Non-standard extension.
template
- inline reference unchecked_emplace_back(BOOST_FWD_REF(Args)...args)
+ BOOST_CONTAINER_FORCEINLINE reference unchecked_emplace_back(BOOST_FWD_REF(Args)...args)
{
BOOST_ASSERT(this->size() < this->capacity());
T* const p = this->priv_raw_end();
@@ -2086,8 +2086,30 @@ private:
//!
//! Complexity: Amortized constant time.
void push_back(T &&x);
+
+ //! Requires: Before the call to this function size() < capacity() must be true.
+ //! Otherwise, the behavior is undefined.
+ //!
+ //! Effects: Inserts a copy of x at the end of the vector.
+ //!
+ //! Throws: If T's copy/move constructor throws.
+ //!
+ //! Complexity: Constant time.
+ void unchecked_push_back(const T &x);
+
+ //! Requires: Before the call to this function size() < capacity() must be true.
+ //! Otherwise, the behavior is undefined.
+ //!
+ //! Effects: Constructs a new element in the end of the vector
+ //! and moves the resources of x to this new element.
+ //!
+ //! Throws: If T's copy/move constructor throws.
+ //!
+ //! Complexity: Constant time.
+ void unchecked_push_back(T &&x);
#else
BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
+ BOOST_MOVE_CONVERSION_AWARE_CATCH(unchecked_push_back, T, void, priv_unchecked_push_back)
#endif
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -2976,10 +2998,20 @@ private:
this->emplace_back(::boost::forward(u));
}
+ template
+ BOOST_CONTAINER_FORCEINLINE void priv_unchecked_push_back(BOOST_FWD_REF(U) u)
+ {
+ this->unchecked_emplace_back(::boost::forward(u));
+ }
+
//Overload to support compiler errors that instantiate too much
inline void priv_push_back(::boost::move_detail::nat)
{}
+ //Overload to support compiler errors that instantiate too much
+ inline void priv_unchecked_push_back(::boost::move_detail::nat)
+ {}
+
inline iterator priv_insert(const_iterator, ::boost::move_detail::nat)
{ return iterator(); }
diff --git a/test/vector_test.hpp b/test/vector_test.hpp
index 70bcad0..aefc1ea 100644
--- a/test/vector_test.hpp
+++ b/test/vector_test.hpp
@@ -42,17 +42,71 @@ namespace boost{
namespace container {
namespace test{
-template
-struct vector_has_function_capacity
-{
- typedef typename Vector::size_type size_type;
- template struct Check;
- template static char func(Check *);
- template static int func(...);
- public:
- static const bool value = sizeof(func(0)) == sizeof(char);
-};
+#define BOOST_VECTOR_TEST_HAS_MEMBER_FUNC(FUNC) \
+ \
+template \
+struct vector_has_function_##FUNC \
+{ \
+ typedef char yes[1]; \
+ typedef char no[2]; \
+ \
+ struct fallback { int FUNC; }; \
+ struct derived : T, fallback {}; \
+ \
+ template \
+ struct check; \
+ \
+ template \
+ static no& test(check*); \
+ \
+ template \
+ static yes& test(...); \
+ \
+ static const bool value = sizeof(test(0)) == sizeof(yes); \
+}; \
+//
+
+BOOST_VECTOR_TEST_HAS_MEMBER_FUNC(capacity)
+BOOST_VECTOR_TEST_HAS_MEMBER_FUNC(unchecked_push_back)
+
+template
+bool vector_unchecked_push_back_test(V1&, V2&, boost::container::dtl::false_type)
+{
+ return true;
+}
+
+template
+bool vector_unchecked_push_back_test(MyBoostVector& , MyStdVector& , boost::container::dtl::true_type)
+{
+ typedef typename MyBoostVector::value_type IntType;
+
+ MyBoostVector bv;
+ MyStdVector sv;
+
+ bv.reserve(10);
+ sv.reserve(10);
+
+ for (std::size_t i = 0, max = bv.capacity(); i < max; ++i) {
+ bv.unchecked_push_back(IntType((int)i));
+ sv.push_back((int)i);
+ }
+
+ if(!test::CheckEqualContainers(bv, sv)) return false;
+
+ bv.clear();
+ sv.clear();
+
+ for (std::size_t i = 0, max = bv.capacity(); i < max; ++i) {
+ IntType move_me((int)i);
+ bv.unchecked_push_back(boost::move(move_me));
+ sv.push_back((int)i);
+ }
+
+ if(!test::CheckEqualContainers(bv, sv)) return false;
+
+ return true;
+}
template
bool vector_capacity_test(V1&, V2&, boost::container::dtl::false_type)
@@ -94,19 +148,20 @@ bool vector_capacity_test(MyBoostVector&boostvector, MyStdVector&stdvector, boos
const std::size_t sz = a.size();
const std::size_t cap = a.capacity();
- a.resize(1000);
+ a.resize(sz);
+ b.resize(sz/10);
a.swap(b);
- if( !(b.capacity() == cap) ) return false;
+ if( !(b.capacity() >= cap) ) return false;
if( !(b.size() == sz) ) return false;
- if( !(a.capacity() != cap) ) return false;
- if( !(a.empty()) ) return false;
+ if( !(a.capacity() >= cap/10) ) return false;
+ if( !(a.size() == sz/10) ) return false;
a.swap(b);
- if( !(a.capacity() == cap) ) return false;
+ if( !(a.capacity() >= cap) ) return false;
if( !(a.size() == sz) ) return false;
- if( !(b.capacity() != cap) ) return false;
- if( !(b.empty()) ) return false;
+ if( !(b.capacity() >= cap/10) ) return false;
+ if( !(b.size() == sz/10) ) return false;
}
return true;
@@ -287,6 +342,9 @@ bool vector_copyable_only(MyBoostVector &boostvector, MyStdVector &stdvector, bo
bcopy2 = boostvector;
scopy2 = stdvector;
if(!test::CheckEqualContainers(bcopy2, scopy2)) return false;
+
+ if(!vector_unchecked_push_back_test(boostvector, stdvector, dtl::bool_::value>()))
+ return 1;
}
return true;