rosidl_runtime_cpp  master
Generate the rosidl interfaces in C++.
bounded_vector.hpp
Go to the documentation of this file.
1 // Copyright 2016 Open Source Robotics Foundation, Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef ROSIDL_RUNTIME_CPP__BOUNDED_VECTOR_HPP_
16 #define ROSIDL_RUNTIME_CPP__BOUNDED_VECTOR_HPP_
17 
18 #include <algorithm>
19 #include <memory>
20 #include <stdexcept>
21 #include <utility>
22 #include <vector>
23 
24 namespace rosidl_runtime_cpp
25 {
26 
28 
35 template<typename Tp, std::size_t UpperBound, typename Alloc = std::allocator<Tp>>
37  : protected std::vector<Tp, Alloc>
38 {
40 
41 public:
42  using typename Base::value_type;
43  using typename Base::pointer;
44  using typename Base::const_pointer;
45  using typename Base::reference;
46  using typename Base::const_reference;
47  using typename Base::iterator;
48  using typename Base::const_iterator;
49  using typename Base::const_reverse_iterator;
50  using typename Base::reverse_iterator;
51  using typename Base::size_type;
52  using typename Base::difference_type;
53  using typename Base::allocator_type;
54 
57  noexcept (std::is_nothrow_default_constructible<Alloc>::value)
58  : Base()
59  {}
60 
62 
65  explicit
67  const typename Base::allocator_type & a)
68  noexcept
69  : Base(a)
70  {}
71 
73 
80  explicit
82  typename Base::size_type n,
83  const typename Base::allocator_type & a = allocator_type())
84  : Base(n, a)
85  {
86  if (n > UpperBound) {
87  throw std::length_error("Exceeded upper bound");
88  }
89  }
90 
92 
100  typename Base::size_type n,
101  const typename Base::value_type & value,
102  const typename Base::allocator_type & a = allocator_type())
103  : Base(n, value, a)
104  {
105  if (n > UpperBound) {
106  throw std::length_error("Exceeded upper bound");
107  }
108  }
109 
111 
120  const BoundedVector & x)
121  : Base(x)
122  {}
123 
125 
132  : Base(std::move(x))
133  {}
134 
136  BoundedVector(const BoundedVector & x, const typename Base::allocator_type & a)
137  : Base(x, a)
138  {}
139 
141 
153  const typename Base::allocator_type & a = typename Base::allocator_type())
154  : Base(l, a)
155  {
156  if (l.size() > UpperBound) {
157  throw std::length_error("Exceeded upper bound");
158  }
159  }
160 
162 
176  template<
177  typename InputIterator
178  >
180  InputIterator first,
181  InputIterator last,
182  const typename Base::allocator_type & a = allocator_type())
183  : Base(first, last, a)
184  {
185  if (size() > UpperBound) {
186  throw std::length_error("Exceeded upper bound");
187  }
188  }
189 
191 
196  ~BoundedVector() noexcept
197  {}
198 
200 
207  BoundedVector &
209  {
210  (void)Base::operator=(x);
211  return *this;
212  }
213 
215 
218  BoundedVector &
220  {
221  (void)Base::operator=(std::move(x));
222  return *this;
223  }
224 
226 
237  BoundedVector &
239  {
240  if (l.size() > UpperBound) {
241  throw std::length_error("Exceeded upper bound");
242  }
243  Base::operator=(l);
244  return *this;
245  }
246 
248 
259  void
261  typename Base::size_type n,
262  const typename Base::value_type & val)
263  {
264  if (n > UpperBound) {
265  throw std::length_error("Exceeded upper bound");
266  }
267  Base::assign(n, val);
268  }
269 
271 
283  template<
284  typename InputIterator
285  >
286  void
287  assign(InputIterator first, InputIterator last)
288  {
290  do_assign(first, last, cat());
291  }
292 
294 
305  void
307  {
308  if (l.size() > UpperBound) {
309  throw std::length_error("Exceeded upper bound");
310  }
311  Base::assign(l);
312  }
313 
314  using Base::begin;
315  using Base::end;
316  using Base::rbegin;
317  using Base::rend;
318  using Base::cbegin;
319  using Base::cend;
320  using Base::crbegin;
321  using Base::crend;
322  using Base::size;
323 
325  typename Base::size_type
326  max_size() const noexcept
327  {
328  return std::min(UpperBound, Base::max_size());
329  }
330 
332 
341  void
342  resize(typename Base::size_type new_size)
343  {
344  if (new_size > UpperBound) {
345  throw std::length_error("Exceeded upper bound");
346  }
347  Base::resize(new_size);
348  }
349 
351 
361  void
363  typename Base::size_type new_size,
364  const typename Base::value_type & x)
365  {
366  if (new_size > UpperBound) {
367  throw std::length_error("Exceeded upper bound");
368  }
369  Base::resize(new_size, x);
370  }
371 
372  using Base::shrink_to_fit;
373  using Base::capacity;
374  using Base::empty;
375 
377 
392  void
393  reserve(typename Base::size_type n)
394  {
395  if (n > UpperBound) {
396  throw std::length_error("Exceeded upper bound");
397  }
398  Base::reserve(n);
399  }
400 
401  using Base::operator[];
402  using Base::at;
403  using Base::front;
404  using Base::back;
405 
407 
410  template<
411  typename T,
412  typename std::enable_if<
415  >::type * = nullptr
416  >
417  T *
418  data() noexcept
419  {
420  return Base::data();
421  }
422 
423  template<
424  typename T,
425  typename std::enable_if<
428  >::type * = nullptr
429  >
430  const T *
431  data() const noexcept
432  {
433  return Base::data();
434  }
435 
437 
447  void
448  push_back(const typename Base::value_type & x)
449  {
450  if (size() >= UpperBound) {
451  throw std::length_error("Exceeded upper bound");
452  }
453  Base::push_back(x);
454  }
455 
456  void
457  push_back(typename Base::value_type && x)
458  {
459  if (size() >= UpperBound) {
460  throw std::length_error("Exceeded upper bound");
461  }
462  Base::push_back(x);
463  }
464 
466 
476  template<typename ... Args>
477  auto
478  emplace_back(Args && ... args)
479  {
480  if (size() >= UpperBound) {
481  throw std::length_error("Exceeded upper bound");
482  }
483  return Base::emplace_back(std::forward<Args>(args)...);
484  }
485 
487 
498  template<typename ... Args>
499  typename Base::iterator
501  typename Base::const_iterator position,
502  Args && ... args)
503  {
504  if (size() >= UpperBound) {
505  throw std::length_error("Exceeded upper bound");
506  }
507  return Base::emplace(position, std::forward<Args>(args) ...);
508  }
509 
511 
522  typename Base::iterator
524  typename Base::const_iterator position,
525  const typename Base::value_type & x)
526  {
527  if (size() >= UpperBound) {
528  throw std::length_error("Exceeded upper bound");
529  }
530  return Base::insert(position, x);
531  }
532 
534 
545  typename Base::iterator
547  typename Base::const_iterator position,
548  typename Base::value_type && x)
549  {
550  if (size() >= UpperBound) {
551  throw std::length_error("Exceeded upper bound");
552  }
553  return Base::insert(position, x);
554  }
555 
557 
569  typename Base::iterator
571  typename Base::const_iterator position,
573  {
574  if (size() + l.size() > UpperBound) {
575  throw std::length_error("Exceeded upper bound");
576  }
577  return Base::insert(position, l);
578  }
579 
581 
594  typename Base::iterator
596  typename Base::const_iterator position,
597  typename Base::size_type n,
598  const typename Base::value_type & x)
599  {
600  if (size() + n > UpperBound) {
601  throw std::length_error("Exceeded upper bound");
602  }
603  return Base::insert(position, n, x);
604  }
605 
607 
621  template<
622  typename InputIterator
623  >
624  typename Base::iterator
626  typename Base::const_iterator position,
627  InputIterator first,
628  InputIterator last)
629  {
631  return do_insert(position, first, last, cat());
632  }
633 
634  using Base::erase;
635  using Base::pop_back;
636  using Base::clear;
637 
638 private:
640  template<
641  typename InputIterator
642  >
643  void
644  do_assign(InputIterator first, InputIterator last, std::input_iterator_tag)
645  {
646  BoundedVector(first, last).swap(*this);
647  }
648 
650  template<
651  typename FwdIterator
652  >
653  void
654  do_assign(FwdIterator first, FwdIterator last, std::forward_iterator_tag)
655  {
656  if (static_cast<std::size_t>(std::distance(first, last)) > UpperBound) {
657  throw std::length_error("Exceeded upper bound");
658  }
659  Base::assign(first, last);
660  }
661 
662  // Insert each value at the end and then rotate them to the desired position.
663  // If the bound is exceeded, the inserted elements are removed again.
664  template<
665  typename InputIterator
666  >
667  typename Base::iterator
668  do_insert(
669  typename Base::const_iterator position,
670  InputIterator first,
671  InputIterator last,
673  {
674  const auto orig_size = size();
675  const auto idx = position - cbegin();
676  try {
677  while (first != last) {
678  push_back(*first++);
679  }
680  } catch (const std::length_error &) {
681  Base::resize(orig_size);
682  throw;
683  }
684  auto pos = begin() + idx;
685  std::rotate(pos, begin() + orig_size, end());
686  return begin() + idx;
687  }
688 
689  template<
690  typename FwdIterator
691  >
692  typename Base::iterator
693  do_insert(
694  typename Base::const_iterator position,
695  FwdIterator first,
696  FwdIterator last,
698  {
699  auto dist = std::distance(first, last);
700  if ((dist < 0) || (size() + static_cast<size_t>(dist) > UpperBound)) {
701  throw std::length_error("Exceeded upper bound");
702  }
703  return Base::insert(position, first, last);
704  }
705 
707 
717  friend bool
719  const BoundedVector & x,
720  const BoundedVector & y)
721  {
722  return static_cast<const Base &>(x) == static_cast<const Base &>(y);
723  }
724 
726 
737  friend bool
739  const BoundedVector & x,
740  const BoundedVector & y)
741  {
742  return static_cast<const Base &>(x) < static_cast<const Base &>(y);
743  }
744 
746  friend bool
748  const BoundedVector & x,
749  const BoundedVector & y)
750  {
751  return static_cast<const Base &>(x) != static_cast<const Base &>(y);
752  }
753 
755  friend bool
757  const BoundedVector & x,
758  const BoundedVector & y)
759  {
760  return static_cast<const Base &>(x) > static_cast<const Base &>(y);
761  }
762 
764  friend bool
766  const BoundedVector & x,
767  const BoundedVector & y)
768  {
769  return static_cast<const Base &>(x) <= static_cast<const Base &>(y);
770  }
771 
773  friend bool
775  const BoundedVector & x,
776  const BoundedVector & y)
777  {
778  return static_cast<const Base &>(x) >= static_cast<const Base &>(y);
779  }
780 };
781 
783 template<typename Tp, std::size_t UpperBound, typename Alloc>
784 inline void
786 {
787  x.swap(y);
788 }
789 
790 } // namespace rosidl_runtime_cpp
791 
792 #endif // ROSIDL_RUNTIME_CPP__BOUNDED_VECTOR_HPP_
rosidl_runtime_cpp::BoundedVector::BoundedVector
BoundedVector(const BoundedVector &x, const typename Base::allocator_type &a)
Copy constructor with alternative allocator.
Definition: bounded_vector.hpp:136
std::is_same
rosidl_runtime_cpp::BoundedVector::~BoundedVector
~BoundedVector() noexcept
The dtor only erases the elements.
Definition: bounded_vector.hpp:196
std::vector::resize
T resize(T... args)
rosidl_runtime_cpp::BoundedVector::resize
void resize(typename Base::size_type new_size)
Resize the BoundedVector to the specified number of elements.
Definition: bounded_vector.hpp:342
rosidl_runtime_cpp::BoundedVector::operator=
BoundedVector & operator=(std::initializer_list< typename Base::value_type > l)
BoundedVector list assignment operator.
Definition: bounded_vector.hpp:238
std::move
T move(T... args)
rosidl_runtime_cpp::BoundedVector::operator!=
friend bool operator!=(const BoundedVector &x, const BoundedVector &y)
Based on operator==.
Definition: bounded_vector.hpp:747
std::vector::reserve
T reserve(T... args)
rosidl_runtime_cpp::BoundedVector::BoundedVector
BoundedVector() noexcept(std::is_nothrow_default_constructible< Alloc >::value)
Create a BoundedVector with no elements.
Definition: bounded_vector.hpp:56
rosidl_runtime_cpp::swap
void swap(BoundedVector< Tp, UpperBound, Alloc > &x, BoundedVector< Tp, UpperBound, Alloc > &y)
See rosidl_runtime_cpp::BoundedVector::swap().
Definition: bounded_vector.hpp:785
rosidl_runtime_cpp::BoundedVector::insert
Base::iterator insert(typename Base::const_iterator position, const typename Base::value_type &x)
Insert given value into BoundedVector before specified iterator.
Definition: bounded_vector.hpp:523
rosidl_runtime_cpp::BoundedVector::BoundedVector
BoundedVector(BoundedVector &&x) noexcept
BoundedVector move constructor.
Definition: bounded_vector.hpp:131
std::vector
std::initializer_list::size
T size(T... args)
rosidl_runtime_cpp::BoundedVector::operator<
friend bool operator<(const BoundedVector &x, const BoundedVector &y)
Vector ordering relation.
Definition: bounded_vector.hpp:738
rosidl_runtime_cpp::BoundedVector::operator>=
friend bool operator>=(const BoundedVector &x, const BoundedVector &y)
Based on operator<.
Definition: bounded_vector.hpp:774
rosidl_runtime_cpp::BoundedVector::operator<=
friend bool operator<=(const BoundedVector &x, const BoundedVector &y)
Based on operator<.
Definition: bounded_vector.hpp:765
std::vector::emplace
T emplace(T... args)
std::input_iterator_tag
rosidl_runtime_cpp::BoundedVector::resize
void resize(typename Base::size_type new_size, const typename Base::value_type &x)
Resize the BoundedVector to the specified number of elements.
Definition: bounded_vector.hpp:362
std::distance
T distance(T... args)
std::rotate
T rotate(T... args)
std::vector::back
T back(T... args)
rosidl_runtime_cpp::BoundedVector::operator==
friend bool operator==(const BoundedVector &x, const BoundedVector &y)
Vector equality comparison.
Definition: bounded_vector.hpp:718
std::vector::front
T front(T... args)
rosidl_runtime_cpp::BoundedVector::emplace
Base::iterator emplace(typename Base::const_iterator position, Args &&... args)
Insert an object in BoundedVector before specified iterator.
Definition: bounded_vector.hpp:500
rosidl_runtime_cpp::BoundedVector::BoundedVector
BoundedVector(std::initializer_list< typename Base::value_type > l, const typename Base::allocator_type &a=typename Base::allocator_type())
Build a BoundedVector from an initializer list.
Definition: bounded_vector.hpp:151
std::vector::clear
T clear(T... args)
std::vector::push_back
T push_back(T... args)
rosidl_runtime_cpp::BoundedVector::insert
Base::iterator insert(typename Base::const_iterator position, typename Base::value_type &&x)
Insert given rvalue into BoundedVector before specified iterator.
Definition: bounded_vector.hpp:546
rosidl_runtime_cpp::BoundedVector::push_back
void push_back(typename Base::value_type &&x)
Definition: bounded_vector.hpp:457
std::vector::capacity
T capacity(T... args)
rosidl_runtime_cpp::BoundedVector::assign
void assign(typename Base::size_type n, const typename Base::value_type &val)
Assign a given value to a BoundedVector.
Definition: bounded_vector.hpp:260
rosidl_runtime_cpp::BoundedVector::BoundedVector
BoundedVector(const typename Base::allocator_type &a) noexcept
Creates a BoundedVector with no elements.
Definition: bounded_vector.hpp:66
rosidl_runtime_cpp::BoundedVector::BoundedVector
BoundedVector(const BoundedVector &x)
BoundedVector copy constructor.
Definition: bounded_vector.hpp:119
rosidl_runtime_cpp::BoundedVector::operator=
BoundedVector & operator=(const BoundedVector &x)
BoundedVector assignment operator.
Definition: bounded_vector.hpp:208
std::vector::at
T at(T... args)
std::enable_if
rosidl_runtime_cpp::BoundedVector::insert
Base::iterator insert(typename Base::const_iterator position, typename Base::size_type n, const typename Base::value_type &x)
Insert a number of copies of given data into the BoundedVector.
Definition: bounded_vector.hpp:595
std::iterator_traits
std::length_error
std::vector::erase
T erase(T... args)
rosidl_runtime_cpp::BoundedVector
A container based on std::vector but with an upper bound.
Definition: bounded_vector.hpp:36
rosidl_runtime_cpp
Definition: action_type_support_decl.hpp:21
std::vector::pop_back
T pop_back(T... args)
rosidl_runtime_cpp::BoundedVector::reserve
void reserve(typename Base::size_type n)
Attempt to preallocate enough memory for specified number of elements.
Definition: bounded_vector.hpp:393
std::vector::max_size
T max_size(T... args)
rosidl_runtime_cpp::BoundedVector::max_size
Base::size_type max_size() const noexcept
Definition: bounded_vector.hpp:326
rosidl_runtime_cpp::BoundedVector::emplace_back
auto emplace_back(Args &&... args)
Add data to the end of the BoundedVector.
Definition: bounded_vector.hpp:478
rosidl_runtime_cpp::BoundedVector::push_back
void push_back(const typename Base::value_type &x)
Add data to the end of the BoundedVector.
Definition: bounded_vector.hpp:448
rosidl_runtime_cpp::BoundedVector::operator=
BoundedVector & operator=(BoundedVector &&x)
BoundedVector move assignment operator
Definition: bounded_vector.hpp:219
std::vector::rend
T rend(T... args)
rosidl_runtime_cpp::BoundedVector::BoundedVector
BoundedVector(InputIterator first, InputIterator last, const typename Base::allocator_type &a=allocator_type())
Build a BoundedVector from a range.
Definition: bounded_vector.hpp:179
std::vector< Tp, std::allocator< Tp > >::swap
T swap(T... args)
std::min
T min(T... args)
rosidl_runtime_cpp::BoundedVector::BoundedVector
BoundedVector(typename Base::size_type n, const typename Base::allocator_type &a=allocator_type())
Create a BoundedVector with default constructed elements.
Definition: bounded_vector.hpp:81
rosidl_runtime_cpp::BoundedVector::BoundedVector
BoundedVector(typename Base::size_type n, const typename Base::value_type &value, const typename Base::allocator_type &a=allocator_type())
Create a BoundedVector with copies of an exemplar element.
Definition: bounded_vector.hpp:99
std::vector::emplace_back
T emplace_back(T... args)
rosidl_runtime_cpp::BoundedVector::insert
Base::iterator insert(typename Base::const_iterator position, InputIterator first, InputIterator last)
Insert a range into the BoundedVector.
Definition: bounded_vector.hpp:625
rosidl_runtime_cpp::BoundedVector::data
const T * data() const noexcept
Definition: bounded_vector.hpp:431
std::vector::begin
T begin(T... args)
std
std::vector::insert
T insert(T... args)
std::vector::operator=
T operator=(T... args)
rosidl_runtime_cpp::BoundedVector::assign
void assign(InputIterator first, InputIterator last)
Assign a range to a BoundedVector.
Definition: bounded_vector.hpp:287
std::vector::empty
T empty(T... args)
std::vector::assign
T assign(T... args)
std::vector::shrink_to_fit
T shrink_to_fit(T... args)
std::size_t
std::vector::end
T end(T... args)
rosidl_runtime_cpp::BoundedVector::operator>
friend bool operator>(const BoundedVector &x, const BoundedVector &y)
Based on operator<.
Definition: bounded_vector.hpp:756
rosidl_runtime_cpp::BoundedVector::assign
void assign(std::initializer_list< typename Base::value_type > l)
Assign an initializer list to a BoundedVector.
Definition: bounded_vector.hpp:306
rosidl_runtime_cpp::BoundedVector::data
T * data() noexcept
Return a pointer such that [data(), data() + size()) is a valid range.
Definition: bounded_vector.hpp:418
rosidl_runtime_cpp::BoundedVector::insert
Base::iterator insert(typename Base::const_iterator position, std::initializer_list< typename Base::value_type > l)
Insert an initializer_list into the BoundedVector.
Definition: bounded_vector.hpp:570
std::vector::data
T data(T... args)
std::vector::rbegin
T rbegin(T... args)
std::initializer_list