Alexandria  2.27.0
SDC-CH common library for the Euclid project
CastVisitor.h
Go to the documentation of this file.
1 
25 #ifndef _TABLE_CASTVISITOR_H
26 #define _TABLE_CASTVISITOR_H
27 
29 #include <boost/tokenizer.hpp>
30 #include <boost/variant/static_visitor.hpp>
31 #include <cmath>
32 #include <sstream>
33 #include <type_traits>
34 #include <typeinfo>
35 #include <vector>
36 
37 namespace Euclid {
38 namespace Table {
39 
40 template <typename To>
41 class CastVisitor : public boost::static_visitor<To> {
42 
43 public:
44  template <typename From>
45  To operator()(const From& from, typename std::enable_if<std::is_same<From, To>::value>::type* = 0) const {
46  return from;
47  }
48 
49  template <typename From>
50  To operator()(const From&, typename std::enable_if<!std::is_same<From, To>::value>::type* = 0) const {
51  throw Elements::Exception() << "CastVisitor cannot convert " << typeid(From).name() << " type to "
52  << typeid(To).name();
53  }
54 };
55 
56 template <>
57 class CastVisitor<std::string> : public boost::static_visitor<std::string> {
58 
59 public:
60  template <typename T>
62  std::stringstream result{};
63  auto it = v.begin();
64  if (it != v.end()) {
65  result << *it;
66  ++it;
67  }
68  while (it != v.end()) {
69  result << ',' << *it;
70  ++it;
71  }
72  return result.str();
73  }
74 
75  template <typename From>
76  std::string operator()(const From& from) const {
77  std::stringstream result{};
78  result << from;
79  return result.str();
80  }
81 };
82 
83 template <>
84 class CastVisitor<double> : public boost::static_visitor<double> {
85 
86  template <typename From>
87  static constexpr bool generic() {
89  }
90 
91 public:
92  template <typename From>
93  double operator()(const From&, typename std::enable_if<!generic<From>()>::type* = 0) const {
94  throw Elements::Exception() << "CastVisitor cannot convert " << typeid(From).name() << " type to "
95  << typeid(double).name();
96  }
97 
98  template <typename From>
99  double operator()(const From& from, typename std::enable_if<generic<From>()>::type* = 0) const {
100  return from;
101  }
102 
103  double operator()(const std::string& from) const {
104  char* endptr = nullptr;
105  double value = std::strtod(from.c_str(), &endptr);
106  if (endptr == from.c_str()) {
107  throw Elements::Exception() << "CastVisitor cannot convert the string '" << from << "' to "
108  << typeid(double).name();
109  }
110  if (value == HUGE_VAL || value == -HUGE_VAL) {
111  throw Elements::Exception() << "CastVisitor overflows converting the string '" << from << "' to "
112  << typeid(double).name();
113  }
114  return value;
115  }
116 };
117 
118 template <>
119 class CastVisitor<float> : public boost::static_visitor<float> {
120 
121  template <typename From>
122  static constexpr bool generic() {
125  }
126 
127 public:
128  template <typename From>
129  double operator()(const From&, typename std::enable_if<!generic<From>()>::type* = 0) const {
130  throw Elements::Exception() << "CastVisitor cannot convert " << typeid(From).name() << " type to "
131  << typeid(float).name();
132  }
133 
134  template <typename From>
135  float operator()(const From& from, typename std::enable_if<generic<From>()>::type* = 0) const {
136  return from;
137  }
138 
139  float operator()(const std::string& from) const {
140  char* endptr = nullptr;
141  float value = std::strtof(from.c_str(), &endptr);
142  if (endptr == from.c_str()) {
143  throw Elements::Exception() << "CastVisitor cannot convert the string '" << from << "' to "
144  << typeid(float).name();
145  }
146  if (value == HUGE_VALF || value == -HUGE_VALF) {
147  throw Elements::Exception() << "CastVisitor overflows converting the string '" << from << "' to "
148  << typeid(float).name();
149  }
150  return value;
151  }
152 };
153 
154 template <>
155 class CastVisitor<int64_t> : public boost::static_visitor<int64_t> {
156 
157  template <typename From>
158  static constexpr bool generic() {
160  }
161 
162 public:
163  template <typename From>
164  double operator()(const From&, typename std::enable_if<!generic<From>()>::type* = 0) const {
165  throw Elements::Exception() << "CastVisitor cannot convert " << typeid(From).name() << " type to "
166  << typeid(int64_t).name();
167  }
168 
169  template <typename From>
170  int64_t operator()(const From& from, typename std::enable_if<generic<From>()>::type* = 0) const {
171  return from;
172  }
173 
174  int64_t operator()(const std::string& from) const {
175  char* endptr = nullptr;
176  int64_t value = std::strtoll(from.c_str(), &endptr, 10);
177  if (endptr == from.c_str()) {
178  throw Elements::Exception() << "CastVisitor cannot convert the string '" << from << "' to "
179  << typeid(int64_t).name();
180  }
181  return value;
182  }
183 };
184 
185 template <>
186 class CastVisitor<int32_t> : public boost::static_visitor<int32_t> {
187 
188  template <typename From>
189  static constexpr bool generic() {
192  }
193 
194 public:
195  template <typename From>
196  double operator()(const From&, typename std::enable_if<!generic<From>()>::type* = 0) const {
197  throw Elements::Exception() << "CastVisitor cannot convert " << typeid(From).name() << " type to "
198  << typeid(int32_t).name();
199  }
200 
201  template <typename From>
202  int32_t operator()(const From& from, typename std::enable_if<generic<From>()>::type* = 0) const {
203  return from;
204  }
205 
206  int32_t operator()(const std::string& from) const {
207  char* endptr = nullptr;
208  int64_t value = std::strtoll(from.c_str(), &endptr, 10);
209  if (endptr == from.c_str()) {
210  throw Elements::Exception() << "CastVisitor cannot convert the string '" << from << "' to "
211  << typeid(int32_t).name();
212  }
213  if (value > INT32_MAX || value < INT32_MIN) {
214  throw Elements::Exception() << "CastVisitor overflows converting the string '" << from << "' to "
215  << typeid(int32_t).name();
216  }
217  return static_cast<int32_t>(value);
218  }
219 };
220 
221 template <typename VectorType>
222 class CastVisitor<std::vector<VectorType>> : public boost::static_visitor<std::vector<VectorType>> {
223 
224 public:
225  template <typename From>
226  std::vector<VectorType> operator()(const From& from) const {
227  std::vector<VectorType> result{};
228  result.push_back(CastVisitor<VectorType>{}(from));
229  return result;
230  }
231 
232  template <typename From>
234  std::vector<VectorType> result{};
235  for (auto v : from) {
236  result.push_back(CastVisitor<VectorType>{}(v));
237  }
238  return result;
239  }
240 
242  std::vector<VectorType> result{};
243  boost::char_separator<char> sep{","};
244  boost::tokenizer<boost::char_separator<char>> tok{from, sep};
245  for (auto& s : tok) {
247  }
248  return result;
249  }
250 
251  // If the types match exactly we avoid an expensive copying
253  return from;
254  }
255 };
256 
257 } /* namespace Table */
258 } /* namespace Euclid */
259 
260 #endif
T begin(T... args)
T c_str(T... args)
double operator()(const From &, typename std::enable_if<!generic< From >()>::type *=0) const
Definition: CastVisitor.h:93
double operator()(const std::string &from) const
Definition: CastVisitor.h:103
double operator()(const From &from, typename std::enable_if< generic< From >()>::type *=0) const
Definition: CastVisitor.h:99
float operator()(const From &from, typename std::enable_if< generic< From >()>::type *=0) const
Definition: CastVisitor.h:135
double operator()(const From &, typename std::enable_if<!generic< From >()>::type *=0) const
Definition: CastVisitor.h:129
float operator()(const std::string &from) const
Definition: CastVisitor.h:139
double operator()(const From &, typename std::enable_if<!generic< From >()>::type *=0) const
Definition: CastVisitor.h:196
int32_t operator()(const std::string &from) const
Definition: CastVisitor.h:206
int32_t operator()(const From &from, typename std::enable_if< generic< From >()>::type *=0) const
Definition: CastVisitor.h:202
int64_t operator()(const std::string &from) const
Definition: CastVisitor.h:174
int64_t operator()(const From &from, typename std::enable_if< generic< From >()>::type *=0) const
Definition: CastVisitor.h:170
double operator()(const From &, typename std::enable_if<!generic< From >()>::type *=0) const
Definition: CastVisitor.h:164
std::string operator()(const std::vector< T > &v) const
Definition: CastVisitor.h:61
std::string operator()(const From &from) const
Definition: CastVisitor.h:76
std::vector< VectorType > operator()(const std::vector< From > &from) const
Definition: CastVisitor.h:233
const std::vector< VectorType > & operator()(const std::vector< VectorType > &from) const
Definition: CastVisitor.h:252
std::vector< VectorType > operator()(const From &from) const
Definition: CastVisitor.h:226
std::vector< VectorType > operator()(const std::string &from) const
Definition: CastVisitor.h:241
To operator()(const From &, typename std::enable_if<!std::is_same< From, To >::value >::type *=0) const
Definition: CastVisitor.h:50
To operator()(const From &from, typename std::enable_if< std::is_same< From, To >::value >::type *=0) const
Definition: CastVisitor.h:45
T end(T... args)
constexpr double s
STL namespace.
T push_back(T... args)
T str(T... args)
T strtod(T... args)
T strtoll(T... args)