NTRT Simulator
 All Classes Files Functions Variables Typedefs Friends Pages
tgTaggables.h
Go to the documentation of this file.
1 /*
2  * Copyright © 2012, United States Government, as represented by the
3  * Administrator of the National Aeronautics and Space Administration.
4  * All rights reserved.
5  *
6  * The NASA Tensegrity Robotics Toolkit (NTRT) v1 platform is licensed
7  * under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * http://www.apache.org/licenses/LICENSE-2.0.
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
15  * either express or implied. See the License for the specific language
16  * governing permissions and limitations under the License.
17 */
18 
25 #ifndef TG_TAGGABLES_H
26 #define TG_TAGGABLES_H
27 
28 #include <iostream> // Testing only
29 #include <algorithm>
30 #include <vector>
31 #include <stdexcept>
32 #include "tgTaggable.h"
33 class tgTaggable;
34 
35 template <class T>
37 {
38 public:
39 
40  tgTaggables() {
41  // Postcondition
42  assert(m_elements.empty());
43  };
44 
51  tgTaggables(std::vector<T>& elements) : m_elements(elements) {
52  // All elements must be unique
53  assertUniqueElements("All elements must be unique.");
54 
55  }
56 
57  virtual ~tgTaggables() {};
58 
63  std::vector<T*> find(std::string tags)
64  {
65  std::vector<T*> result;
66  for(int i = 0; i < m_elements.size(); i++) {
67  if(_taggable(&m_elements[i])->hasAllTags(tags)) {
68  result.push_back(&(m_elements[i]));
69  }
70  }
71  return result;
72  }
73 
74  int size() const
75  {
76  return m_elements.size();
77  }
78 
79  std::vector<T*> findAll()
80  {
81  std::vector<T*> result;
82  for(int i = 0; i < m_elements.size(); i++) {
83  result.push_back(&(m_elements[i]));
84  }
85  return result;
86  }
87 
88  std::vector<T*> findUntagged()
89  {
90  std::vector<T*> result;
91  for(int i = 0; i < m_elements.size(); i++) {
92  tgTaggable* t = _taggable(&m_elements[i]);
93  if(t->hasNoTags()) {
94  result.push_back(&(m_elements[i]));
95  }
96  }
97  return result;
98  }
99 
100  static bool contains(std::vector<T*> haystack, const T* needle)
101  {
102  return std::find(haystack.begin(), haystack.end(), needle) != haystack.end();
103  }
104 
105  bool contains(const T& needle) const
106  {
107  //return std::find(m_elements.begin(), m_elements.end(), needle) != m_elements.end(); // generates errors??
108  for(typename std::vector<T>::const_iterator it = m_elements.begin(); it != m_elements.end(); it++) {
109  if(&(*it) == &needle)
110  return true;
111  }
112  return false;
113  }
114 
115 
122  T& operator[](int key) {
123  assertKeyExists(key);
124  return m_elements[key];
125  }
126 
127  const T& operator[](int key) const {
128  assertKeyExists(key);
129  return m_elements[key];
130  }
131 
135  T& operator-=(const T& other) {
136  this->removeElements(other.getElements());
137  return *this;
138  }
139 
140  T& operator-=(const std::vector<T*> other) {
141  this->removeElements(other);
142  return *this;
143  }
144 
145  T& operator+=(const T& other) {
146  this->addElement(other);
147  return *this;
148  }
149 
150  T& operator+=(const std::vector<T*> other) {
151  this->addElements(other);
152  return *this;
153  }
154 
155 
156 protected:
157 
158  // @todo: think about uniqueness -- if not unique, throw an error? return -1?
159  int addElement(T element)
160  {
161  // @todo: make sure the element is unique
162  assert(!elementExists(element)); // segfault?
163  assertUnique(element);
164  m_elements.push_back(element);
165  return m_elements.size(); // This is the index that was created.
166  }
167 
168  void addElements(std::vector<T*> elements)
169  {
170  for(int i = 0; i < elements.size(); i++) {
171  this->addElement(elements[i]);
172  }
173  }
174 
175  void setElement(int key, T element) {
176  assert((0 <= key) && (key <= m_elements.size()));
177  m_elements[key] = element;
178  }
179 
180  std::vector<T>& getElements()
181  {
182  return m_elements;
183  };
184 
185  const std::vector<T>& getElements() const
186  {
187  return m_elements;
188  };
189 
190  void removeElement(const T& element) {
191  m_elements.erase(std::remove(m_elements.begin(), m_elements.end(), element), m_elements.end());
192  }
193 
194  void removeElement(const T* element) {
195  m_elements.erase(std::remove(m_elements.begin(), m_elements.end(), *element), m_elements.end());
196  }
197 
198  void removeElements(const std::vector<T>& elements) {
199  for(int i = 0; i < elements.size(); i++) {
200  removeElement(elements[i]);
201  }
202  }
203 
204  void removeElements(const std::vector<T*>& elements) {
205  for(int i = 0; i < elements.size(); i++) {
206  removeElement(elements[i]);
207  }
208  }
209 
210  // To make subclassing operators easier...
211  T& getElement(int key)
212  {
213  return m_elements[key];
214  }
215 
216  // To make subclassing operators easier...
217  const T& getElement(int key) const
218  {
219  return m_elements[key];
220  }
221 
228  bool keyExists(int key) const
229  {
230  return (0 <= key) && (key < m_elements.size());
231  }
232 
233  // @todo: FIX THIS -- segfaults, etc. -- what's going on?
234  bool elementExists(const T& element) const
235  {
236  //return std::find(m_elements.begin(), m_elements.end(), element) != m_elements.end(); // segfault?
237  for(int i = 0; i < m_elements.size(); i++) {
238  // This is a little strange to me, but at least it doesn't cause a segfault...
239  const T* elem =& m_elements[i];
240  if (elem == &element) {
241  return true;
242  }
243  }
244  return false;
245  }
246 
247  void assertKeyExists(int key, std::string message = "Element at index does not exist") const
248  {
249  if(!keyExists(key)) {
250  std::stringstream ss;
251  ss << key;
252  throw std::out_of_range(message + " (index "+ ss.str() + ").");
253  }
254  }
255 
256  void assertUnique(T& element, std::string message = "Taggable elements must be unique.") {
257  if(elementExists(element)) {
258  throw std::logic_error(message);
259  }
260  }
261 
262  void assertUniqueElements(std::string message = "Taggable elements must be unique.") const
263  {
264  /* Note: this throws a "Most vexing parse" error (http://en.wikipedia.org/wiki/Most_vexing_parse)
265  // Note: This would probably work if we implemented operator< on tgPair...
266  */
267 
268  if(! std::set<T>(m_elements.begin(), m_elements.end()).size() ==
269  m_elements.size()) {
270  throw std::logic_error(message);
271  }
272 
273  }
274 
275  // Cast T to taggable (after all, T must be a tgTaggable in the first place, but )
276  // there doesn't seem to be a way to enforce that with c++ templates...
277  tgTaggable* _taggable(T* obj) {
278  return static_cast<tgTaggable*>(obj);
279  }
280 
281 private:
282  std::vector<T> m_elements;
283 };
284 
285 
286 #endif
T & operator-=(const T &other)
Definition: tgTaggables.h:135
std::vector< T * > find(std::string tags)
Definition: tgTaggables.h:63
T & operator[](int key)
Definition: tgTaggables.h:122
Contains the definition of class tgTaggable $Id$.
tgTaggables(std::vector< T > &elements)
Definition: tgTaggables.h:51
bool keyExists(int key) const
Definition: tgTaggables.h:228