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
00018
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
00067 template <typename T>
00068 explicit Any(const T& value, EnableIntegral<T> = 0) : _any(int64_t(value))
00069 {
00070 }
00071
00072
00073 template <typename T>
00074 explicit Any(const T& value, EnableNonIntegral<T> = 0) : _any(value)
00075 {
00076 }
00077
00078
00079
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 }
00194
00195 #endif // VARNUMBER_H