safe_any.hpp
Go to the documentation of this file.
1 #ifndef SAFE_ANY_VARNUMBER_H
2 #define SAFE_ANY_VARNUMBER_H
3 
4 #include <exception>
5 #include <algorithm>
6 #include <iostream>
7 #include <chrono>
8 #include <string>
9 #include <cstring>
10 #include <type_traits>
11 #include "any.hpp"
12 #include "demangle_util.h"
13 #include "convert_impl.hpp"
14 #include "expected.hpp"
15 #include "strcat.hpp"
16 #include "strcat.hpp"
17 
18 namespace BT
19 {
20 // Rational: since type erased numbers will always use at least 8 bytes
21 // it is faster to cast everything to either double, uint64_t or int64_t.
22 class Any
23 {
24  template <typename T>
25  using EnableIntegral =
26  typename std::enable_if<std::is_integral<T>::value || std::is_enum<T>::value>::type*;
27 
28  template <typename T>
29  using EnableNonIntegral =
30  typename std::enable_if<!std::is_integral<T>::value && !std::is_enum<T>::value>::type*;
31 
32  template <typename T>
33  using EnableString = typename std::enable_if<std::is_same<T, std::string>::value>::type*;
34 
35  template <typename T>
36  using EnableArithmetic = typename std::enable_if<std::is_arithmetic<T>::value>::type*;
37 
38  template <typename T>
39  using EnableEnum = typename std::enable_if<std::is_enum<T>::value>::type*;
40 
41  template <typename T>
42  using EnableUnknownType =
43  typename std::enable_if<!std::is_arithmetic<T>::value && !std::is_enum<T>::value &&
44  !std::is_same<T, std::string>::value>::type*;
45 
46  public:
47  Any(): _original_type(nullptr)
48  {
49  }
50 
51  ~Any() = default;
52 
53  Any(const Any& other) : _any(other._any), _original_type( other._original_type )
54  {
55  }
56 
57  Any(Any&& other) : _any( std::move(other._any) ), _original_type( other._original_type )
58  {
59  }
60 
61  explicit Any(const double& value) : _any(value), _original_type( &typeid(double) )
62  {
63  }
64 
65  explicit Any(const uint64_t& value) : _any(value), _original_type( &typeid(uint64_t) )
66  {
67  }
68 
69  explicit Any(const float& value) : _any(double(value)), _original_type( &typeid(float) )
70  {
71  }
72 
73  explicit Any(const std::string& str) : _any(SafeAny::SimpleString(str)), _original_type( &typeid(std::string) )
74  {
75  }
76 
77  explicit Any(const char* str) : _any(SafeAny::SimpleString(str)), _original_type( &typeid(std::string) )
78  {
79  }
80 
81  explicit Any(const SafeAny::SimpleString& str) : _any(str), _original_type( &typeid(std::string) )
82  {
83  }
84 
85  // all the other integrals are casted to int64_t
86  template <typename T>
87  explicit Any(const T& value, EnableIntegral<T> = 0) : _any(int64_t(value)), _original_type( &typeid(T) )
88  {
89  }
90 
91  // default for other custom types
92  template <typename T>
93  explicit Any(const T& value, EnableNonIntegral<T> = 0) : _any(value), _original_type( &typeid(T) )
94  {
95  static_assert(!std::is_reference<T>::value, "Any can not contain references");
96  }
97 
98  Any& operator = (const Any& other)
99  {
100  this->_any = other._any;
101  this->_original_type = other._original_type;
102  return *this;
103  }
104 
105  bool isNumber() const
106  {
107  return _any.type() == typeid(int64_t) ||
108  _any.type() == typeid(uint64_t) ||
109  _any.type() == typeid(double);
110  }
111 
112  bool isString() const
113  {
114  return _any.type() == typeid(SafeAny::SimpleString);
115  }
116 
117  // this is different from any_cast, because if allows safe
118  // conversions between arithmetic values.
119  template <typename T>
120  T cast() const
121  {
122  static_assert(!std::is_reference<T>::value, "Any::cast uses value semantic, can not cast to reference");
123 
124  if( _any.empty() )
125  {
126  throw std::runtime_error("Any::cast failed because it is empty");
127  }
128  if (_any.type() == typeid(T))
129  {
130  return linb::any_cast<T>(_any);
131  }
132  else
133  {
134  auto res = convert<T>();
135  if( !res )
136  {
137  throw std::runtime_error( res.error() );
138  }
139  return res.value();
140  }
141  }
142 
143  const std::type_info& type() const noexcept
144  {
145  return *_original_type;
146  }
147 
148  const std::type_info& castedType() const noexcept
149  {
150  return _any.type();
151  }
152 
153  bool empty() const noexcept
154  {
155  return _any.empty();
156  }
157 
158  private:
160  const std::type_info* _original_type;
161 
162  //----------------------------
163 
164  template <typename DST>
165  nonstd::expected<DST,std::string> convert(EnableString<DST> = 0) const
166  {
167  const auto& type = _any.type();
168 
169  if (type == typeid(SafeAny::SimpleString))
170  {
171  return linb::any_cast<SafeAny::SimpleString>(_any).toStdString();
172  }
173  else if (type == typeid(int64_t))
174  {
175  return std::to_string(linb::any_cast<int64_t>(_any));
176  }
177  else if (type == typeid(uint64_t))
178  {
179  return std::to_string(linb::any_cast<uint64_t>(_any));
180  }
181  else if (type == typeid(double))
182  {
183  return std::to_string(linb::any_cast<double>(_any));
184  }
185 
186  return nonstd::make_unexpected( errorMsg<DST>() );
187  }
188 
189  template <typename DST>
190  nonstd::expected<DST,std::string> convert(EnableArithmetic<DST> = 0) const
191  {
192  using SafeAny::details::convertNumber;
193  DST out;
194 
195  const auto& type = _any.type();
196 
197  if (type == typeid(int64_t))
198  {
199  convertNumber<int64_t, DST>(linb::any_cast<int64_t>(_any), out);
200  }
201  else if (type == typeid(uint64_t))
202  {
203  convertNumber<uint64_t, DST>(linb::any_cast<uint64_t>(_any), out);
204  }
205  else if (type == typeid(double))
206  {
207  convertNumber<double, DST>(linb::any_cast<double>(_any), out);
208  }
209  else{
210  return nonstd::make_unexpected( errorMsg<DST>() );
211  }
212  return out;
213  }
214 
215  template <typename DST>
216  nonstd::expected<DST,std::string> convert(EnableEnum<DST> = 0) const
217  {
218  using SafeAny::details::convertNumber;
219 
220  const auto& type = _any.type();
221 
222  if (type == typeid(int64_t))
223  {
224  uint64_t out = linb::any_cast<int64_t>(_any);
225  return static_cast<DST>(out);
226  }
227  else if (type == typeid(uint64_t))
228  {
229  uint64_t out = linb::any_cast<uint64_t>(_any);
230  return static_cast<DST>(out);
231  }
232 
233  return nonstd::make_unexpected( errorMsg<DST>() );
234  }
235 
236  template <typename DST>
237  nonstd::expected<DST,std::string> convert(EnableUnknownType<DST> = 0) const
238  {
239  return nonstd::make_unexpected( errorMsg<DST>() );
240  }
241 
242  template <typename T>
243  std::string errorMsg() const
244  {
245  return StrCat("[Any::convert]: no known safe conversion between [",
246  demangle( _any.type() ), "] and [", demangle( typeid(T) ),"]");
247  }
248 };
249 
250 } // end namespace BT
251 
252 #endif // VARNUMBER_H
BT
Definition: ex01_wrap_legacy.cpp:29
SafeAny
Definition: convert_impl.hpp:8
BT::demangle
std::string demangle(char const *name)
Definition: demangle_util.h:72
BT::Any::EnableEnum
typename std::enable_if< std::is_enum< T >::value >::type * EnableEnum
Definition: safe_any.hpp:39
BT::Any
Definition: safe_any.hpp:22
BT::Any::operator=
Any & operator=(const Any &other)
Definition: safe_any.hpp:98
BT::Any::convert
nonstd::expected< DST, std::string > convert(EnableArithmetic< DST >=0) const
Definition: safe_any.hpp:190
BT::Any::isString
bool isString() const
Definition: safe_any.hpp:112
BT::Any::castedType
const std::type_info & castedType() const noexcept
Definition: safe_any.hpp:148
BT::Any::Any
Any()
Definition: safe_any.hpp:47
BT::Any::~Any
~Any()=default
BT::Any::Any
Any(const std::string &str)
Definition: safe_any.hpp:73
linb::any::empty
bool empty() const noexcept
Returns true if *this has no contained object, otherwise false.
Definition: any.hpp:123
BT::Any::EnableArithmetic
typename std::enable_if< std::is_arithmetic< T >::value >::type * EnableArithmetic
Definition: safe_any.hpp:36
BT::Any::convert
nonstd::expected< DST, std::string > convert(EnableUnknownType< DST >=0) const
Definition: safe_any.hpp:237
strcat.hpp
BT::Any::Any
Any(const Any &other)
Definition: safe_any.hpp:53
BT::Any::convert
nonstd::expected< DST, std::string > convert(EnableEnum< DST >=0) const
Definition: safe_any.hpp:216
linb::any::type
const std::type_info & type() const noexcept
If *this has a contained object of type T, typeid(T); otherwise typeid(void).
Definition: any.hpp:129
BT::Any::Any
Any(const T &value, EnableIntegral< T >=0)
Definition: safe_any.hpp:87
BT::Any::Any
Any(const T &value, EnableNonIntegral< T >=0)
Definition: safe_any.hpp:93
BT::Any::isNumber
bool isNumber() const
Definition: safe_any.hpp:105
BT::Any::Any
Any(const char *str)
Definition: safe_any.hpp:77
BT::Any::EnableString
typename std::enable_if< std::is_same< T, std::string >::value >::type * EnableString
Definition: safe_any.hpp:33
BT::Any::Any
Any(const SafeAny::SimpleString &str)
Definition: safe_any.hpp:81
BT::Any::empty
bool empty() const noexcept
Definition: safe_any.hpp:153
BT::Any::errorMsg
std::string errorMsg() const
Definition: safe_any.hpp:243
BT::Any::Any
Any(const uint64_t &value)
Definition: safe_any.hpp:65
SafeAny::SimpleString
Definition: simple_string.hpp:10
demangle_util.h
BT::Any::Any
Any(Any &&other)
Definition: safe_any.hpp:57
BT::Any::cast
T cast() const
Definition: safe_any.hpp:120
BT::StrCat
std::string StrCat()
Definition: strcat.hpp:47
BT::Any::Any
Any(const double &value)
Definition: safe_any.hpp:61
convert_impl.hpp
BT::Any::EnableIntegral
typename std::enable_if< std::is_integral< T >::value||std::is_enum< T >::value >::type * EnableIntegral
Definition: safe_any.hpp:26
linb::any
Definition: any.hpp:34
BT::Any::EnableUnknownType
typename std::enable_if<!std::is_arithmetic< T >::value &&!std::is_enum< T >::value &&!std::is_same< T, std::string >::value >::type * EnableUnknownType
Definition: safe_any.hpp:44
std
Definition: any.hpp:455
BT::Any::type
const std::type_info & type() const noexcept
Definition: safe_any.hpp:143
BT::Any::_any
linb::any _any
Definition: safe_any.hpp:159
expected.hpp
BT::Any::convert
nonstd::expected< DST, std::string > convert(EnableString< DST >=0) const
Definition: safe_any.hpp:165
any.hpp
BT::Any::EnableNonIntegral
typename std::enable_if<!std::is_integral< T >::value &&!std::is_enum< T >::value >::type * EnableNonIntegral
Definition: safe_any.hpp:30
nonstd::sv_lite::to_string
std::basic_string< CharT, Traits > to_string(basic_string_view< CharT, Traits > v)
Definition: string_view.hpp:1414
BT::Any::Any
Any(const float &value)
Definition: safe_any.hpp:69
BT::Any::_original_type
const std::type_info * _original_type
Definition: safe_any.hpp:160


behaviortree_cpp_v3
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Wed Jun 26 2024 02:51:19