From 9ffe2148b9c249b8539a27745062d6c2c1716f2b Mon Sep 17 00:00:00 2001 From: cho3 Date: Fri, 7 Jun 2019 11:16:14 -0700 Subject: [PATCH] Add emplace_back, move_assignment to BoundedVector (#385) * Add emplace_back, move_assignment to BoundedVector Signed-off-by: Christopher Ho * Address reviewer comments: - Use `auto` for portability - Add unit tests - Add documentation Signed-off-by: Christopher Ho --- .../rosidl_generator_cpp/bounded_vector.hpp | 42 ++++++++++++++++++- .../test/test_bounded_vector.cpp | 18 ++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/rosidl_generator_cpp/include/rosidl_generator_cpp/bounded_vector.hpp b/rosidl_generator_cpp/include/rosidl_generator_cpp/bounded_vector.hpp index 8370e596c..37e48b6a6 100644 --- a/rosidl_generator_cpp/include/rosidl_generator_cpp/bounded_vector.hpp +++ b/rosidl_generator_cpp/include/rosidl_generator_cpp/bounded_vector.hpp @@ -207,8 +207,18 @@ class BoundedVector BoundedVector & operator=(const BoundedVector & __x) { - reinterpret_cast *>(this)->operator=( - *reinterpret_cast *>(&__x)); + (void)_Base::operator=(__x); + return *this; + } + + /// %BoundedVector move assignment operator + /** + * \param __x A %BoundedVector of identical element and allocator types. + */ + BoundedVector & + operator=(BoundedVector && __x) + { + (void)_Base::operator=(std::forward<_Base &&>(__x)); return *this; } @@ -454,6 +464,27 @@ class BoundedVector _Base::push_back(__x); } + /// Add data to the end of the %BoundedVector. + /** + * This is a typical stack operation. + * The function creates an element at the end of the %BoundedVector + * and assigns the given data to it. + * Due to the nature of a %BoundedVector this operation can be done in + * constant time if the %BoundedVector has preallocated space + * available. + * + * \param args Arguments to be forwarded to the constructor of _Tp + */ + template + auto + emplace_back(Args && ... args) + { + if (size() >= _UpperBound) { + throw std::length_error("Exceeded upper bound"); + } + return _Base::emplace_back(std::forward(args)...); + } + /// Insert an object in %BoundedVector before specified iterator. /** * This function will insert an object of type T constructed with @@ -607,6 +638,13 @@ class BoundedVector using _Base::erase; using _Base::pop_back; using _Base::clear; + +private: + /// Cast to base type, to make it easier to dispatch to base implementations + operator _Base &() + { + return *this; + } }; /// Vector equality comparison. diff --git a/rosidl_generator_cpp/test/test_bounded_vector.cpp b/rosidl_generator_cpp/test/test_bounded_vector.cpp index 58aedd352..de6fc00bf 100644 --- a/rosidl_generator_cpp/test/test_bounded_vector.cpp +++ b/rosidl_generator_cpp/test/test_bounded_vector.cpp @@ -13,6 +13,7 @@ // limitations under the License. #include +#include #include "rosidl_generator_cpp/bounded_vector.hpp" @@ -32,3 +33,20 @@ TEST(rosidl_generator_cpp, bounded_vector) { auto l = {1, 2, 3}; ASSERT_THROW(v = l, std::length_error); } + +TEST(rosidl_generator_cpp, bounded_vector_rvalue) { + rosidl_generator_cpp::BoundedVector v; + // emplace back + ASSERT_EQ(v.size(), 0u); + ASSERT_EQ(v.max_size(), 2u); + v.emplace_back(1); + v.emplace_back(2); + ASSERT_THROW(v.emplace_back(3), std::length_error); + ASSERT_EQ(v.size(), 2u); + // move assignment + decltype(v) vv; + vv = std::move(v); + ASSERT_EQ(vv.size(), 2u); + ASSERT_EQ(vv[0], 1); + ASSERT_EQ(vv[1], 2); +}