.. _program_listing_file_include_rosidl_runtime_cpp_bounded_vector.hpp: Program Listing for File bounded_vector.hpp =========================================== |exhale_lsh| :ref:`Return to documentation for file ` (``include/rosidl_runtime_cpp/bounded_vector.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp // Copyright 2016 Open Source Robotics Foundation, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef ROSIDL_RUNTIME_CPP__BOUNDED_VECTOR_HPP_ #define ROSIDL_RUNTIME_CPP__BOUNDED_VECTOR_HPP_ #include #include #include #include #include namespace rosidl_runtime_cpp { template> class BoundedVector : protected std::vector { using Base = std::vector; public: using typename Base::value_type; using typename Base::pointer; using typename Base::const_pointer; using typename Base::reference; using typename Base::const_reference; using typename Base::iterator; using typename Base::const_iterator; using typename Base::const_reverse_iterator; using typename Base::reverse_iterator; using typename Base::size_type; using typename Base::difference_type; using typename Base::allocator_type; BoundedVector() noexcept (std::is_nothrow_default_constructible::value) : Base() {} explicit BoundedVector( const typename Base::allocator_type & a) noexcept : Base(a) {} explicit BoundedVector( typename Base::size_type n, const typename Base::allocator_type & a = allocator_type()) : Base(n, a) { if (n > UpperBound) { throw std::length_error("Exceeded upper bound"); } } BoundedVector( typename Base::size_type n, const typename Base::value_type & value, const typename Base::allocator_type & a = allocator_type()) : Base(n, value, a) { if (n > UpperBound) { throw std::length_error("Exceeded upper bound"); } } BoundedVector( const BoundedVector & x) : Base(x) {} BoundedVector(BoundedVector && x) noexcept : Base(std::move(x)) {} BoundedVector(const BoundedVector & x, const typename Base::allocator_type & a) : Base(x, a) {} BoundedVector( std::initializer_list l, const typename Base::allocator_type & a = typename Base::allocator_type()) : Base(l, a) { if (l.size() > UpperBound) { throw std::length_error("Exceeded upper bound"); } } template< typename InputIterator > BoundedVector( InputIterator first, InputIterator last, const typename Base::allocator_type & a = allocator_type()) : Base(first, last, a) { if (size() > UpperBound) { throw std::length_error("Exceeded upper bound"); } } ~BoundedVector() noexcept {} BoundedVector & operator=(const BoundedVector & x) { (void)Base::operator=(x); return *this; } BoundedVector & operator=(BoundedVector && x) { (void)Base::operator=(std::move(x)); return *this; } BoundedVector & operator=(std::initializer_list l) { if (l.size() > UpperBound) { throw std::length_error("Exceeded upper bound"); } Base::operator=(l); return *this; } void assign( typename Base::size_type n, const typename Base::value_type & val) { if (n > UpperBound) { throw std::length_error("Exceeded upper bound"); } Base::assign(n, val); } template< typename InputIterator > void assign(InputIterator first, InputIterator last) { using cat = typename std::iterator_traits::iterator_category; do_assign(first, last, cat()); } void assign(std::initializer_list l) { if (l.size() > UpperBound) { throw std::length_error("Exceeded upper bound"); } Base::assign(l); } using Base::begin; using Base::end; using Base::rbegin; using Base::rend; using Base::cbegin; using Base::cend; using Base::crbegin; using Base::crend; using Base::size; typename Base::size_type max_size() const noexcept { return std::min(UpperBound, Base::max_size()); } void resize(typename Base::size_type new_size) { if (new_size > UpperBound) { throw std::length_error("Exceeded upper bound"); } Base::resize(new_size); } void resize( typename Base::size_type new_size, const typename Base::value_type & x) { if (new_size > UpperBound) { throw std::length_error("Exceeded upper bound"); } Base::resize(new_size, x); } using Base::shrink_to_fit; using Base::capacity; using Base::empty; void reserve(typename Base::size_type n) { if (n > UpperBound) { throw std::length_error("Exceeded upper bound"); } Base::reserve(n); } using Base::operator[]; using Base::at; using Base::front; using Base::back; template< typename T, typename std::enable_if< !std::is_same::value && !std::is_same::value >::type * = nullptr > T * data() noexcept { return Base::data(); } template< typename T, typename std::enable_if< !std::is_same::value && !std::is_same::value >::type * = nullptr > const T * data() const noexcept { return Base::data(); } void push_back(const typename Base::value_type & x) { if (size() >= UpperBound) { throw std::length_error("Exceeded upper bound"); } Base::push_back(x); } void push_back(typename Base::value_type && x) { if (size() >= UpperBound) { throw std::length_error("Exceeded upper bound"); } Base::push_back(x); } template auto emplace_back(Args && ... args) { if (size() >= UpperBound) { throw std::length_error("Exceeded upper bound"); } return Base::emplace_back(std::forward(args)...); } template typename Base::iterator emplace( typename Base::const_iterator position, Args && ... args) { if (size() >= UpperBound) { throw std::length_error("Exceeded upper bound"); } return Base::emplace(position, std::forward(args) ...); } typename Base::iterator insert( typename Base::const_iterator position, const typename Base::value_type & x) { if (size() >= UpperBound) { throw std::length_error("Exceeded upper bound"); } return Base::insert(position, x); } typename Base::iterator insert( typename Base::const_iterator position, typename Base::value_type && x) { if (size() >= UpperBound) { throw std::length_error("Exceeded upper bound"); } return Base::insert(position, x); } typename Base::iterator insert( typename Base::const_iterator position, std::initializer_list l) { if (size() + l.size() > UpperBound) { throw std::length_error("Exceeded upper bound"); } return Base::insert(position, l); } typename Base::iterator insert( typename Base::const_iterator position, typename Base::size_type n, const typename Base::value_type & x) { if (size() + n > UpperBound) { throw std::length_error("Exceeded upper bound"); } return Base::insert(position, n, x); } template< typename InputIterator > typename Base::iterator insert( typename Base::const_iterator position, InputIterator first, InputIterator last) { using cat = typename std::iterator_traits::iterator_category; return do_insert(position, first, last, cat()); } using Base::erase; using Base::pop_back; using Base::clear; private: template< typename InputIterator > void do_assign(InputIterator first, InputIterator last, std::input_iterator_tag) { BoundedVector(first, last).swap(*this); } template< typename FwdIterator > void do_assign(FwdIterator first, FwdIterator last, std::forward_iterator_tag) { if (static_cast(std::distance(first, last)) > UpperBound) { throw std::length_error("Exceeded upper bound"); } Base::assign(first, last); } // Insert each value at the end and then rotate them to the desired position. // If the bound is exceeded, the inserted elements are removed again. template< typename InputIterator > typename Base::iterator do_insert( typename Base::const_iterator position, InputIterator first, InputIterator last, std::input_iterator_tag) { const auto orig_size = size(); const auto idx = position - cbegin(); try { while (first != last) { push_back(*first++); } } catch (const std::length_error &) { Base::resize(orig_size); throw; } auto pos = begin() + idx; std::rotate(pos, begin() + orig_size, end()); return begin() + idx; } template< typename FwdIterator > typename Base::iterator do_insert( typename Base::const_iterator position, FwdIterator first, FwdIterator last, std::forward_iterator_tag) { auto dist = std::distance(first, last); if ((dist < 0) || (size() + static_cast(dist) > UpperBound)) { throw std::length_error("Exceeded upper bound"); } return Base::insert(position, first, last); } friend bool operator==( const BoundedVector & x, const BoundedVector & y) { return static_cast(x) == static_cast(y); } friend bool operator<( const BoundedVector & x, const BoundedVector & y) { return static_cast(x) < static_cast(y); } friend bool operator!=( const BoundedVector & x, const BoundedVector & y) { return static_cast(x) != static_cast(y); } friend bool operator>( const BoundedVector & x, const BoundedVector & y) { return static_cast(x) > static_cast(y); } friend bool operator<=( const BoundedVector & x, const BoundedVector & y) { return static_cast(x) <= static_cast(y); } friend bool operator>=( const BoundedVector & x, const BoundedVector & y) { return static_cast(x) >= static_cast(y); } }; template inline void swap(BoundedVector & x, BoundedVector & y) { x.swap(y); } } // namespace rosidl_runtime_cpp #endif // ROSIDL_RUNTIME_CPP__BOUNDED_VECTOR_HPP_