safe_any.hpp
Go to the documentation of this file.
00001 #ifndef SAFE_ANY_VARNUMBER_H
00002 #define SAFE_ANY_VARNUMBER_H
00003 
00004 #include <exception>
00005 #include <algorithm>
00006 #include <iostream>
00007 #include <chrono>
00008 #include <string>
00009 #include <cstring>
00010 #include <type_traits>
00011 #include "any.hpp"
00012 #include "demangle_util.h"
00013 #include "convert_impl.hpp"
00014 
00015 namespace SafeAny
00016 {
00017 // Rational: since type erased numbers will always use at least 8 bytes
00018 // it is faster to cast everything to either double, uint64_t or int64_t.
00019 class Any
00020 {
00021     template <typename T>
00022     using EnableIntegral =
00023         typename std::enable_if<std::is_integral<T>::value || std::is_enum<T>::value>::type*;
00024 
00025     template <typename T>
00026     using EnableNonIntegral =
00027         typename std::enable_if<!std::is_integral<T>::value && !std::is_enum<T>::value>::type*;
00028 
00029     template <typename T>
00030     using EnableString = typename std::enable_if<std::is_same<T, std::string>::value>::type*;
00031 
00032     template <typename T>
00033     using EnableArithmetic = typename std::enable_if<std::is_arithmetic<T>::value>::type*;
00034 
00035     template <typename T>
00036     using EnableEnum = typename std::enable_if<std::is_enum<T>::value>::type*;
00037 
00038     template <typename T>
00039     using EnableUnknownType =
00040         typename std::enable_if<!std::is_arithmetic<T>::value && !std::is_enum<T>::value &&
00041                                 !std::is_same<T, std::string>::value>::type*;
00042 
00043   public:
00044     Any()
00045     {
00046     }
00047 
00048     ~Any() = default;
00049 
00050     Any(const double& value) : _any(value)
00051     {
00052     }
00053 
00054     Any(const uint64_t& value) : _any(value)
00055     {
00056     }
00057 
00058     Any(const float& value) : _any(double(value))
00059     {
00060     }
00061 
00062     Any(const std::string& str) : _any(SimpleString(str))
00063     {
00064     }
00065 
00066     // all the other integrals are casted to int64_t
00067     template <typename T>
00068     explicit Any(const T& value, EnableIntegral<T> = 0) : _any(int64_t(value))
00069     {
00070     }
00071 
00072     // default for other custom types
00073     template <typename T>
00074     explicit Any(const T& value, EnableNonIntegral<T> = 0) : _any(value)
00075     {
00076     }
00077 
00078     // this is different from any_cast, because if allows safe
00079     // conversions between arithmetic values.
00080     template <typename T>
00081     T cast() const
00082     {
00083         if (_any.type() == typeid(T))
00084         {
00085             return linb::any_cast<T>(_any);
00086         }
00087         else
00088         {
00089             return convert<T>();
00090         }
00091     }
00092 
00093     const std::type_info& type() const noexcept
00094     {
00095         return _any.type();
00096     }
00097 
00098   private:
00099     linb::any _any;
00100 
00101     //----------------------------
00102 
00103     template <typename DST>
00104     DST convert(EnableString<DST> = 0) const
00105     {
00106         const auto& type = _any.type();
00107 
00108         if (type == typeid(SimpleString))
00109         {
00110             return linb::any_cast<SimpleString>(_any).toStdString();
00111         }
00112         else if (type == typeid(int64_t))
00113         {
00114             return std::to_string(linb::any_cast<int64_t>(_any));
00115         }
00116         else if (type == typeid(uint64_t))
00117         {
00118             return std::to_string(linb::any_cast<uint64_t>(_any));
00119         }
00120         else if (type == typeid(double))
00121         {
00122             return std::to_string(linb::any_cast<double>(_any));
00123         }
00124 
00125         throw errorMsg<DST>();
00126     }
00127 
00128     template <typename DST>
00129     DST convert(EnableArithmetic<DST> = 0) const
00130     {
00131         using details::convertNumber;
00132         DST out;
00133 
00134         const auto& type = _any.type();
00135 
00136         if (type == typeid(int64_t))
00137         {
00138             convertNumber<int64_t, DST>(linb::any_cast<int64_t>(_any), out);
00139         }
00140         else if (type == typeid(uint64_t))
00141         {
00142             convertNumber<uint64_t, DST>(linb::any_cast<uint64_t>(_any), out);
00143         }
00144         else if (type == typeid(double))
00145         {
00146             convertNumber<double, DST>(linb::any_cast<double>(_any), out);
00147         }
00148         else
00149         {
00150             throw errorMsg<DST>();
00151         }
00152         return out;
00153     }
00154 
00155     template <typename DST>
00156     DST convert(EnableEnum<DST> = 0) const
00157     {
00158         using details::convertNumber;
00159 
00160         const auto& type = _any.type();
00161 
00162         if (type == typeid(int64_t))
00163         {
00164             uint64_t out = linb::any_cast<int64_t>(_any);
00165             return static_cast<DST>(out);
00166         }
00167         else if (type == typeid(uint64_t))
00168         {
00169             uint64_t out = linb::any_cast<uint64_t>(_any);
00170             return static_cast<DST>(out);
00171         }
00172 
00173         throw errorMsg<DST>();
00174     }
00175 
00176     template <typename DST>
00177     DST convert(EnableUnknownType<DST> = 0) const
00178     {
00179         throw errorMsg<DST>();
00180     }
00181 
00182     template <typename T>
00183     std::runtime_error errorMsg() const
00184     {
00185         char buffer[1024];
00186         sprintf(buffer, "[Any::convert]: no known safe conversion between %s and %s",
00187                 BT::demangle( _any.type().name() ).c_str(),
00188                 BT::demangle( typeid(T).name() ).c_str() );
00189         return std::runtime_error(buffer);
00190     }
00191 };
00192 
00193 }   // end namespace VarNumber
00194 
00195 #endif   // VARNUMBER_H


behaviortree_cpp
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Sat Feb 2 2019 03:50:10