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 
49 
50 // Consider inheritance TupleType->TupleBase, so all S-typed stuff here?
51 template <typename S>
52 struct TupleType {
53 
55 
62  static
63  const S neutral_value;
64 };
65 
66 template <typename S>
68 
69 
74 template <typename S, size_t N=2>
75 class TupleBase {
76 
77 public:
78 
80  typedef S value_type;
81 
82  typedef S* iterator;
83  typedef S const* const_iterator;
84 
85  static const size_t storageTypeSize;
86 
87  TupleBase(){};
88 
89  virtual
90  ~TupleBase(){};
91 
93 
96  static inline
97  size_t size(){
98  return N;
99  }
100 
101  virtual
102  const_iterator begin() const = 0;
103 
104  virtual
105  const_iterator end() const = 0;
106 
107  virtual
108  iterator begin() = 0;
109 
110  virtual
111  iterator end() = 0;
112 
114 
118  const S & at(size_t i) const {
119  //(std::stringstream("UniTuple: ") << __FUNCTION__).r
120  if (i<N)
121  return *(begin() + i);
122  else {
123  /*
124  std::stringstream sstr;
125  sstr << // TypeName<tuple_t>::str() << ':' <<
126  __FUNCTION__ << " index overflow:" << i;
127  throw std::runtime_error(sstr.str());
128  */
129  throw std::runtime_error(StringBuilder<' '>(__FUNCTION__, "index overflow:", i));
130  }
131  }
132 
133  const S & operator[](size_t i) const {
134  return at(i);
135  }
136 
138 
142  S & at(size_t i){
143  if (i<N)
144  return *(begin() + i);
145  else {
146  /*
147  std::stringstream sstr;
148  sstr << // << TypeName<tuple_t>::str() << ':'
149  __FUNCTION__ << " index overflow:" << i;
150  throw std::runtime_error(sstr.str());
151  */
152  throw std::runtime_error(StringBuilder<' '>(__FUNCTION__, "index overflow:", i));
153  }
154  }
155 
156  S & operator[](size_t i){
157  return at(i);
158  }
159 
160 
162  bool operator==(const tuplebase_t &t) const {
163  const_iterator it = begin();
164  const_iterator tit = t.begin();
165  while (it != end()){
166  if (*it != *tit)
167  return false;
168  ++it;
169  ++tit;
170  }
171  return true;
172  }
173 
175 
178  bool operator==(const value_type &t) const {
179  //
180  for (const auto e: *this){
181  if (e != t){
182  return false;
183  }
184  }
185  /*
186  * const_iterator it = begin();
187  while (it != end()){
188  if (*it != t)
189  return false;
190  ++it;
191  }*/
192  return true;
193  }
194 
195 
197  bool operator!=(const tuplebase_t &t) const {
198  return !(*this == t);
199  }
200 
202  template <class T>
203  T & toSequence(T & sequence) const {
204  sequence.clear();
205  for (const_iterator it = begin(); it != end(); ++it){
206  sequence.insert(sequence.end(), *it);
207  }
208  return sequence;
209  }
210 
211 
212 
214  //tuple_t & set(const tuple_t & t){
215  void set(const tuplebase_t & t){
216  if (&t != this){
217  this->assignSequence(t);
218  }
219  // this->assign(t);
220  /*
221  if (&t != &this->tuple()){
222  this->assign(t);
223  }
224  */
225  //return *this;
226  }
227 
229  template <class T2, size_t N2=2>
230  //tuple_t & set(const UniTuple<T2,N2> & t){
231  //void set(const UniTuple<T2,N2> & t){
232  void set(const TupleBase<T2,N2> & t){
233  /*
234  if (&t == this){
235  throw std::runtime_error(StringBuilder<>(__FILE__, ':', __FUNCTION__, ": self-assignment violation: ", t, " [", drain::TypeName<TupleBase<T2,N2> >::str(), "]"));
236  }
237  */
238  this->assignSequence(t, true); // by default LENIENT, or how should it be?
239  // return *this;
240  }
241 
242 
243  inline
244  void set(const S & arg) {
245  setIndexed(0, arg);
246  this->updateTuple();
247  }
248 
250  // Variadic-argument member set function.
251  // https://en.cppreference.com/w/cpp/language/parameter_pack
252  template<typename ... SS>
253  inline
254  void set(const S & arg, const SS &... rest) {
255  setIndexed(0, arg, rest...);
256  this->updateTuple();
257  }
258 
259  template<typename T>
260  inline
261  void set(std::initializer_list<T> l){
262  this->assignSequence(l);
263  }
264 
265 
267  /*
268  tuplebase_t & assign(const tuplebase_t & t){
269  if (&t != this){
270  this->assignSequence(t);
271  }
272  return *this;
273  }
274 
275  tuplebase_t & assign(const value_type & value){
276  this->fill(value);
277  updateTuple();
278  return *this;
279  }
280  */
281 
283 
286  template <class T>
287  tuplebase_t & assignSequence(T & sequence, bool LENIENT = false){
288  typename T::const_iterator cit = sequence.begin();
289  iterator it = begin();
290  while (cit != sequence.end()){
291  if (it == end()){
292  if (LENIENT){
293  return *this;
294  }
295  else {
296  throw std::runtime_error(StringBuilder<':'>(__FILE__, ':', __FUNCTION__, ": index overflow in assigning: ", *cit));
297  /*
298  std::stringstream sstr;
299  sstr << __FILE__ << ':' << __FUNCTION__ << ": run out of indices in assigning: " << *cit;
300  throw std::runtime_error(sstr.str());
301  */
302  }
303  break;
304  }
305  // break;
306  *it = *cit;
307  ++it;
308  ++cit;
309  }
310  return *this;
311  }
312 
313 
315  void fill(S i){
316  for (iterator it = begin(); it != end(); ++it){
317  *it = i;
318  }
319  }
320 
321  inline
322  void clear(){
323  fill(S());
324  }
325 
326 
330  virtual
331  std::ostream & toStream(std::ostream & ostr, char separator=',') const {
332  char sep = 0;
333  for (const_iterator it = begin(); it != end(); ++it){
334  if (sep)
335  ostr << sep;
336  else
337  sep = separator;
338  ostr << *it; //(*this)[i];
339  }
340  return ostr;
341  }
342 
343  std::string toStr(char separator=',') const {
344  std::stringstream sstr;
345  toStream(sstr, separator);
346  return sstr.str();
347  }
348 
349 
350 // protected?
351 
352  // AreaGeom etc.
353  virtual inline
354  void updateTuple(){};
355 
356 
357 protected:
358 
360  void setIndexed(size_t i){
361  //std::cout << __FUNCTION__ << " complete " << i << '\n';
362  this->updateTuple();
363  }
364 
366  template<typename T2, typename ... TT>
367  void setIndexed(size_t i, T2 arg, const TT &... rest){
368  if (i>=N){
369  throw std::runtime_error(StringBuilder<>(__FILE__, ':', __FUNCTION__, ": index (", i, ") overflow in assigning: ", arg, ",..."));
370  return;
371  }
372  // std::cout << __FUNCTION__ << "N=" << N << " arg=" << arg << " remaining:" << i << std::endl;
373  this->at(i) = static_cast<S>(arg);
374  setIndexed(i+1, rest...);
375  }
376 
377 };
378 
379 
380 template <typename S, size_t N>
381 const size_t TupleBase<S,N>::storageTypeSize = sizeof(S);
382 
383 
384 template <class S, size_t N>
385 std::ostream & operator<<(std::ostream & ostr, const TupleBase<S,N> & tuple){
386  return tuple.toStream(ostr);
387 }
388 
389 
390 template <typename S, size_t N>
391 struct TypeName<TupleBase<S,N> > {
392 
393  static const std::string & str(){
394  if (N == 0){
395  static const std::string name = drain::StringBuilder<>("PseudoTuple<", drain::TypeName<S>::str(),',' , drain::TypeName<S>::str(),">");
396  return name;
397  }
398  else {
399  static const std::string name = drain::StringBuilder<>("PseudoTuple<", drain::TypeName<S>::str(),',' , drain::TypeName<S>::str(),',' , N, ">");
400  return name;
401  }
402  }
403 
404 };
405 
406 
407 
408 } // drain
409 
410 
411 #endif
Definition: StringBuilder.h:58
Definition: TupleBase.h:75
S & at(size_t i)
Return reference to element i.
Definition: TupleBase.h:142
static size_t size()
Return the number of elements.
Definition: TupleBase.h:97
virtual std::ostream & toStream(std::ostream &ostr, char separator=',') const
Definition: TupleBase.h:331
void setIndexed(size_t i)
Argument stack endpoint function; final step of variadic argument set(arg, ...) .
Definition: TupleBase.h:360
bool operator!=(const tuplebase_t &t) const
Inequality operator.
Definition: TupleBase.h:197
tuplebase_t & assignSequence(T &sequence, bool LENIENT=false)
Proposed for tuples only; derived classes should not shadow this.
Definition: TupleBase.h:287
T & toSequence(T &sequence) const
Copy elements to a Sequence, like stl::list, stl::set or stl::vector.
Definition: TupleBase.h:203
const S & at(size_t i) const
Return const reference to element i.
Definition: TupleBase.h:118
void fill(S i)
Set all the elements to i.
Definition: TupleBase.h:315
bool operator==(const tuplebase_t &t) const
Equality operator.
Definition: TupleBase.h:162
void setIndexed(size_t i, T2 arg, const TT &... rest)
Worker called by set(T2 arg, T2 arg2, ...)
Definition: TupleBase.h:367
void set(const TupleBase< T2, N2 > &t)
Assign tuple of different type and/or size.
Definition: TupleBase.h:232
void set(const S &arg, const SS &... rest)
Set element(s).
Definition: TupleBase.h:254
bool operator==(const value_type &t) const
Equality operator against single value.
Definition: TupleBase.h:178
Definition: DataSelector.cpp:1277
Definition: TupleBase.h:52
static const S neutral_value
Zero, by default. For enum types, must be explicitly given.
Definition: TupleBase.h:63
Definition: Type.h:542
static const std::string name
Default implementation: name returned by std::type_info::name()
Definition: Type.h:558