TupleBase.h
1 /*
2 
3 MIT License
4 
5 Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13 
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
16 
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 SOFTWARE.
24 
25 */
26 /*
27 Part of Rack development has been done in the BALTRAD projects part-financed
28 by the European Union (European Regional Development Fund and European
29 Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30 */
31 
32 
33 #ifndef DRAIN_TUPLE_BASE
34 #define DRAIN_TUPLE_BASE
35 
36 #include <cstddef>
37 #include <iostream>
38 #include <sstream>
39 #include <typeinfo>
40 #include <stdexcept>
41 #include <string>
42 //#include <set>
43 
44 #include "StringBuilder.h"
45 #include "Type.h" // TypeName
46 
47 namespace drain {
48 
53 template <typename S, size_t N=2>
54 class TupleBase {
55 
56 public:
57 
59  typedef S value_type;
60 
61  typedef S* iterator;
62  typedef S const* const_iterator;
63 
64  static const size_t storageTypeSize;
65 
66  TupleBase(){};
67 
68  virtual
69  ~TupleBase(){};
70 
72 
75  static inline
76  size_t size(){
77  return N;
78  }
79 
80  virtual
81  const_iterator begin() const = 0;
82 
83  virtual
84  const_iterator end() const = 0;
85 
86  virtual
87  iterator begin() = 0;
88 
89  virtual
90  iterator end() = 0;
91 
93 
97  const S & at(size_t i) const {
98  //(std::stringstream("UniTuple: ") << __FUNCTION__).r
99  if (i<N)
100  return *(begin() + i);
101  else {
102  /*
103  std::stringstream sstr;
104  sstr << // TypeName<tuple_t>::str() << ':' <<
105  __FUNCTION__ << " index overflow:" << i;
106  throw std::runtime_error(sstr.str());
107  */
108  throw std::runtime_error(StringBuilder<' '>(__FUNCTION__, "index overflow:", i));
109  }
110  }
111 
112  const S & operator[](size_t i) const {
113  return at(i);
114  }
115 
117 
121  S & at(size_t i){
122  if (i<N)
123  return *(begin() + i);
124  else {
125  /*
126  std::stringstream sstr;
127  sstr << // << TypeName<tuple_t>::str() << ':'
128  __FUNCTION__ << " index overflow:" << i;
129  throw std::runtime_error(sstr.str());
130  */
131  throw std::runtime_error(StringBuilder<' '>(__FUNCTION__, "index overflow:", i));
132  }
133  }
134 
135  S & operator[](size_t i){
136  return at(i);
137  }
138 
139 
141  bool operator==(const tuplebase_t &t) const {
142  const_iterator it = begin();
143  const_iterator tit = t.begin();
144  while (it != end()){
145  if (*it != *tit)
146  return false;
147  ++it;
148  ++tit;
149  }
150  return true;
151  }
152 
154  bool operator!=(const tuplebase_t &t) const {
155  return !(*this == t);
156  }
157 
159  template <class T>
160  T & toSequence(T & sequence) const {
161  sequence.clear();
162  for (const_iterator it = begin(); it != end(); ++it){
163  sequence.insert(sequence.end(), *it);
164  }
165  return sequence;
166  }
167 
168 
169 
171  //tuple_t & set(const tuple_t & t){
172  void set(const tuplebase_t & t){
173  if (&t != this){
174  this->assignSequence(t);
175  }
176  // this->assign(t);
177  /*
178  if (&t != &this->tuple()){
179  this->assign(t);
180  }
181  */
182  //return *this;
183  }
184 
186  template <class T2, size_t N2=2>
187  //tuple_t & set(const UniTuple<T2,N2> & t){
188  //void set(const UniTuple<T2,N2> & t){
189  void set(const TupleBase<T2,N2> & t){
190  /*
191  if (&t == this){
192  throw std::runtime_error(StringBuilder<>(__FILE__, ':', __FUNCTION__, ": self-assignment violation: ", t, " [", drain::TypeName<TupleBase<T2,N2> >::str(), "]"));
193  }
194  */
195  this->assignSequence(t, true); // by default LENIENT, or how should it be?
196  // return *this;
197  }
198 
199 
200  inline
201  void set(const S & arg) {
202  setIndexed(0, arg);
203  this->updateTuple();
204  }
205 
207  // Variadic-argument member set function.
208  // https://en.cppreference.com/w/cpp/language/parameter_pack
209  template<typename ... SS>
210  inline
211  void set(const S & arg, const SS &... rest) {
212  setIndexed(0, arg, rest...);
213  this->updateTuple();
214  }
215 
216  template<typename T>
217  inline
218  void set(std::initializer_list<T> l){
219  this->assignSequence(l);
220  }
221 
222 
224  /*
225  tuplebase_t & assign(const tuplebase_t & t){
226  if (&t != this){
227  this->assignSequence(t);
228  }
229  return *this;
230  }
231 
232  tuplebase_t & assign(const value_type & value){
233  this->fill(value);
234  updateTuple();
235  return *this;
236  }
237  */
238 
240 
243  template <class T>
244  tuplebase_t & assignSequence(T & sequence, bool LENIENT = false){
245  typename T::const_iterator cit = sequence.begin();
246  iterator it = begin();
247  while (cit != sequence.end()){
248  if (it == end()){
249  if (LENIENT){
250  return *this;
251  }
252  else {
253  throw std::runtime_error(StringBuilder<':'>(__FILE__, ':', __FUNCTION__, ": index overflow in assigning: ", *cit));
254  /*
255  std::stringstream sstr;
256  sstr << __FILE__ << ':' << __FUNCTION__ << ": run out of indices in assigning: " << *cit;
257  throw std::runtime_error(sstr.str());
258  */
259  }
260  break;
261  }
262  // break;
263  *it = *cit;
264  ++it;
265  ++cit;
266  }
267  return *this;
268  }
269 
270 
272  void fill(S i){
273  for (iterator it = begin(); it != end(); ++it){
274  *it = i;
275  }
276  }
277 
278  inline
279  void clear(){
280  fill(S());
281  }
282 
283 
287  virtual
288  std::ostream & toStream(std::ostream & ostr, char separator=',') const {
289  char sep = 0;
290  for (const_iterator it = begin(); it != end(); ++it){
291  if (sep)
292  ostr << sep;
293  else
294  sep = separator;
295  ostr << *it; //(*this)[i];
296  }
297  return ostr;
298  }
299 
300  std::string toStr(char separator=',') const {
301  std::stringstream sstr;
302  toStream(sstr, separator);
303  return sstr.str();
304  }
305 
306 
307 // protected?
308 
309  // AreaGeom etc.
310  virtual inline
311  void updateTuple(){};
312 
313 
314 protected:
315 
317  void setIndexed(size_t i){
318  //std::cout << __FUNCTION__ << " complete " << i << '\n';
319  this->updateTuple();
320  }
321 
323  template<typename T2, typename ... TT>
324  void setIndexed(size_t i, T2 arg, const TT &... rest){
325  if (i>=N){
326  throw std::runtime_error(StringBuilder<>(__FILE__, ':', __FUNCTION__, ": index (", i, ") overflow in assigning: ", arg, ",..."));
327  return;
328  }
329  // std::cout << __FUNCTION__ << "N=" << N << " arg=" << arg << " remaining:" << i << std::endl;
330  this->at(i) = static_cast<S>(arg);
331  setIndexed(i+1, rest...);
332  }
333 
334 };
335 
336 
337 template <typename S, size_t N>
338 const size_t TupleBase<S,N>::storageTypeSize = sizeof(S);
339 
340 
341 template <class S, size_t N>
342 std::ostream & operator<<(std::ostream & ostr, const TupleBase<S,N> & tuple){
343  return tuple.toStream(ostr);
344 }
345 
346 
347 template <typename S, size_t N>
348 struct TypeName<TupleBase<S,N> > {
349 
350  static const std::string & str(){
351  if (N == 0){
352  static const std::string name = drain::StringBuilder<>("PseudoTuple<", drain::TypeName<S>::str(),',' , drain::TypeName<S>::str(),">");
353  return name;
354  }
355  else {
356  static const std::string name = drain::StringBuilder<>("PseudoTuple<", drain::TypeName<S>::str(),',' , drain::TypeName<S>::str(),',' , N, ">");
357  return name;
358  }
359  }
360 
361 };
362 
363 
364 
365 } // drain
366 
367 
368 #endif
Definition: StringBuilder.h:58
Definition: TupleBase.h:54
S & at(size_t i)
Return reference to element i.
Definition: TupleBase.h:121
static size_t size()
Return the number of elements.
Definition: TupleBase.h:76
virtual std::ostream & toStream(std::ostream &ostr, char separator=',') const
Definition: TupleBase.h:288
void setIndexed(size_t i)
Argument stack endpoint function; final step of variadic argument set(arg, ...) .
Definition: TupleBase.h:317
bool operator!=(const tuplebase_t &t) const
Inequality operator.
Definition: TupleBase.h:154
tuplebase_t & assignSequence(T &sequence, bool LENIENT=false)
Proposed for tuples only; derived classes should not shadow this.
Definition: TupleBase.h:244
T & toSequence(T &sequence) const
Copy elements to a Sequence, like stl::list, stl::set or stl::vector.
Definition: TupleBase.h:160
const S & at(size_t i) const
Return const reference to element i.
Definition: TupleBase.h:97
void fill(S i)
Set all the elements to i.
Definition: TupleBase.h:272
bool operator==(const tuplebase_t &t) const
Equality operator.
Definition: TupleBase.h:141
void setIndexed(size_t i, T2 arg, const TT &... rest)
Worker called by set(T2 arg, T2 arg2, ...)
Definition: TupleBase.h:324
void set(const TupleBase< T2, N2 > &t)
Assign tuple of different type and/or size.
Definition: TupleBase.h:189
void set(const S &arg, const SS &... rest)
Set element(s).
Definition: TupleBase.h:211
Definition: DataSelector.cpp:1277
Definition: Type.h:542
static const std::string name
Default implementation: name returned by std::type_info::name()
Definition: Type.h:558