Added unchecked_push_back to vector/small_vector/static_vector

This commit is contained in:
Ion Gaztañaga
2026-03-28 00:42:21 +01:00
parent 3c30008aca
commit d56993febc
4 changed files with 138 additions and 20 deletions
+1 -1
View File
@@ -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]
+29 -1
View File
@@ -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 <tt>size() < capacity()</tt>. 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<true> option is set and the container runs out of capacity.
//!
//! @par Complexity
//! Constant O(1).
void unchecked_push_back(value_type const& value);
//! @pre <tt>size() < capacity()</tt>. 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<true> option is set and the container runs out of capacity.
//!
//! @par Complexity
//! Constant O(1).
void unchecked_push_back(value_type &&value);
//! @pre <tt>!empty()</tt>
//!
+33 -1
View File
@@ -1984,7 +1984,7 @@ private:
//!
//! <b>Note</b>: Non-standard extension.
template<class ...Args>
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:
//!
//! <b>Complexity</b>: Amortized constant time.
void push_back(T &&x);
//! <b>Requires</b>: Before the call to this function size() < capacity() must be true.
//! Otherwise, the behavior is undefined.
//!
//! <b>Effects</b>: Inserts a copy of x at the end of the vector.
//!
//! <b>Throws</b>: If T's copy/move constructor throws.
//!
//! <b>Complexity</b>: Constant time.
void unchecked_push_back(const T &x);
//! <b>Requires</b>: Before the call to this function size() < capacity() must be true.
//! Otherwise, the behavior is undefined.
//!
//! <b>Effects</b>: Constructs a new element in the end of the vector
//! and moves the resources of x to this new element.
//!
//! <b>Throws</b>: If T's copy/move constructor throws.
//!
//! <b>Complexity</b>: 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>(u));
}
template <class U>
BOOST_CONTAINER_FORCEINLINE void priv_unchecked_push_back(BOOST_FWD_REF(U) u)
{
this->unchecked_emplace_back(::boost::forward<U>(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(); }
+75 -17
View File
@@ -42,17 +42,71 @@ namespace boost{
namespace container {
namespace test{
template<class Vector>
struct vector_has_function_capacity
{
typedef typename Vector::size_type size_type;
template <typename U, size_type (U::*)() const> struct Check;
template <typename U> static char func(Check<U, &U::capacity> *);
template <typename U> static int func(...);
public:
static const bool value = sizeof(func<Vector>(0)) == sizeof(char);
};
#define BOOST_VECTOR_TEST_HAS_MEMBER_FUNC(FUNC) \
\
template<class T> \
struct vector_has_function_##FUNC \
{ \
typedef char yes[1]; \
typedef char no[2]; \
\
struct fallback { int FUNC; }; \
struct derived : T, fallback {}; \
\
template <typename U, U> \
struct check; \
\
template <typename U> \
static no& test(check<int fallback::*, &U::FUNC>*); \
\
template <typename U> \
static yes& test(...); \
\
static const bool value = sizeof(test<derived>(0)) == sizeof(yes); \
}; \
//
BOOST_VECTOR_TEST_HAS_MEMBER_FUNC(capacity)
BOOST_VECTOR_TEST_HAS_MEMBER_FUNC(unchecked_push_back)
template<class V1, class V2>
bool vector_unchecked_push_back_test(V1&, V2&, boost::container::dtl::false_type)
{
return true;
}
template<class MyBoostVector, class MyStdVector>
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<class V1, class V2>
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_<vector_has_function_unchecked_push_back<MyBoostVector>::value>()))
return 1;
}
return true;