NTRT Simulator  v1.1
 All Classes Namespaces 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 
26 #ifndef TG_TAGGABLES_H
27 #define TG_TAGGABLES_H
28 
29 #include <iostream> // Testing only
30 #include <algorithm>
31 #include <vector>
32 #include <stdexcept>
33 #include "tgTaggable.h"
34 class tgTaggable;
35 
36 template <class T>
38 {
39 public:
40 
41  tgTaggables() {
42  // Postcondition
43  assert(m_elements.empty());
44  };
45 
52  tgTaggables(std::vector<T>& elements) : m_elements(elements) {
53  // All elements must be unique
54  assertUniqueElements("All elements must be unique.");
55 
56  }
57 
58  virtual ~tgTaggables() {};
59 
64  std::vector<T*> find(std::string tags)
65  {
66  std::vector<T*> result;
67  for(int i = 0; i < m_elements.size(); i++) {
68  if(_taggable(&m_elements[i])->hasAllTags(tags)) {
69  result.push_back(&(m_elements[i]));
70  }
71  }
72  return result;
73  }
74 
75  int size() const
76  {
77  return m_elements.size();
78  }
79 
80  std::vector<T*> findAll()
81  {
82  std::vector<T*> result;
83  for(int i = 0; i < m_elements.size(); i++) {
84  result.push_back(&(m_elements[i]));
85  }
86  return result;
87  }
88 
89  std::vector<T*> findUntagged()
90  {
91  std::vector<T*> result;
92  for(int i = 0; i < m_elements.size(); i++) {
93  tgTaggable* t = _taggable(&m_elements[i]);
94  if(t->hasNoTags()) {
95  result.push_back(&(m_elements[i]));
96  }
97  }
98  return result;
99  }
100 
101  static bool contains(std::vector<T*> haystack, const T* needle)
102  {
103  return std::find(haystack.begin(), haystack.end(), needle) != haystack.end();
104  }
105 
106  bool contains(const T& needle) const
107  {
108  //return std::find(m_elements.begin(), m_elements.end(), needle) != m_elements.end(); // generates errors??
109  for(typename std::vector<T>::const_iterator it = m_elements.begin(); it != m_elements.end(); it++) {
110  if(&(*it) == &needle)
111  return true;
112  }
113  return false;
114  }
115 
116 
123  T& operator[](int key) {
124  assertKeyExists(key);
125  return m_elements[key];
126  }
127 
128  const T& operator[](int key) const {
129  assertKeyExists(key);
130  return m_elements[key];
131  }
132 
136  T& operator-=(const T& other) {
137  this->removeElements(other.getElements());
138  return *this;
139  }
140 
141  T& operator-=(const std::vector<T*> other) {
142  this->removeElements(other);
143  return *this;
144  }
145 
146  T& operator+=(const T& other) {
147  this->addElement(other);
148  return *this;
149  }
150 
151  T& operator+=(const std::vector<T*> other) {
152  this->addElements(other);
153  return *this;
154  }
155 
156 
157 protected:
158 
159  // @todo: think about uniqueness -- if not unique, throw an error? return -1?
160  int addElement(T element)
161  {
162  // @todo: make sure the element is unique
163  assert(!elementExists(element)); // segfault?
164  assertUnique(element);
165  m_elements.push_back(element);
166  return m_elements.size(); // This is the index that was created.
167  }
168 
169  void addElements(std::vector<T*> elements)
170  {
171  for(int i = 0; i < elements.size(); i++) {
172  this->addElement(elements[i]);
173  }
174  }
175 
176  void setElement(int key, T element) {
177  assert((0 <= key) && (key <= m_elements.size()));
178  m_elements[key] = element;
179  }
180 
181  std::vector<T>& getElements()
182  {
183  return m_elements;
184  };
185 
186  const std::vector<T>& getElements() const
187  {
188  return m_elements;
189  };
190 
191  void removeElement(const T& element) {
192  m_elements.erase(std::remove(m_elements.begin(), m_elements.end(), element), m_elements.end());
193  }
194 
195  void removeElement(const T* element) {
196  m_elements.erase(std::remove(m_elements.begin(), m_elements.end(), *element), m_elements.end());
197  }
198 
199  void removeElements(const std::vector<T>& elements) {
200  for(int i = 0; i < elements.size(); i++) {
201  removeElement(elements[i]);
202  }
203  }
204 
205  void removeElements(const std::vector<T*>& elements) {
206  for(int i = 0; i < elements.size(); i++) {
207  removeElement(elements[i]);
208  }
209  }
210 
211  // To make subclassing operators easier...
212  T& getElement(int key)
213  {
214  return m_elements[key];
215  }
216 
217  // To make subclassing operators easier...
218  const T& getElement(int key) const
219  {
220  return m_elements[key];
221  }
222 
229  bool keyExists(int key) const
230  {
231  return (0 <= key) && (key < m_elements.size());
232  }
233 
234  // @todo: FIX THIS -- segfaults, etc. -- what's going on?
235  bool elementExists(const T& element) const
236  {
237  //return std::find(m_elements.begin(), m_elements.end(), element) != m_elements.end(); // segfault?
238  for(int i = 0; i < m_elements.size(); i++) {
239  // This is a little strange to me, but at least it doesn't cause a segfault...
240  const T* elem =& m_elements[i];
241  if (elem == &element) {
242  return true;
243  }
244  }
245  return false;
246  }
247 
248  void assertKeyExists(int key, std::string message = "Element at index does not exist") const
249  {
250  if(!keyExists(key)) {
251  std::stringstream ss;
252  ss << key;
253  throw std::out_of_range(message + " (index "+ ss.str() + ").");
254  }
255  }
256 
257  void assertUnique(T& element, std::string message = "Taggable elements must be unique.") {
258  if(elementExists(element)) {
259  throw std::logic_error(message);
260  }
261  }
262 
263  void assertUniqueElements(std::string message = "Taggable elements must be unique.") const
264  {
265  /* Note: this throws a "Most vexing parse" error (http://en.wikipedia.org/wiki/Most_vexing_parse)
266  // Note: This would probably work if we implemented operator< on tgPair...
267  */
268 
269  if(! std::set<T>(m_elements.begin(), m_elements.end()).size() ==
270  m_elements.size()) {
271  throw std::logic_error(message);
272  }
273 
274  }
275 
276  // Cast T to taggable (after all, T must be a tgTaggable in the first place, but )
277  // there doesn't seem to be a way to enforce that with c++ templates...
278  tgTaggable* _taggable(T* obj) {
279  return static_cast<tgTaggable*>(obj);
280  }
281 
282 private:
283  std::vector<T> m_elements;
284 };
285 
286 
287 #endif
T & operator-=(const T &other)
Definition: tgTaggables.h:136
std::vector< T * > find(std::string tags)
Definition: tgTaggables.h:64
T & operator[](int key)
Definition: tgTaggables.h:123
Contains the definition of class tgTaggable.
tgTaggables(std::vector< T > &elements)
Definition: tgTaggables.h:52
bool keyExists(int key) const
Definition: tgTaggables.h:229