convert_impl.hpp
Go to the documentation of this file.
00001 #ifndef CONVERT_IMPL_HPP
00002 #define CONVERT_IMPL_HPP
00003 
00004 #include <type_traits>
00005 #include <exception>
00006 #include "simple_string.hpp"
00007 
00008 namespace SafeAny
00009 {
00010 namespace details
00011 {
00012 template <typename BoolCondition>
00013 using EnableIf = typename std::enable_if<BoolCondition::value, void>::type;
00014 
00015 template <typename T>
00016 struct is_integer
00017   : std::integral_constant<bool, std::is_integral<T>::value && !std::is_same<T, bool>::value &&
00018                                      !std::is_same<T, char>::value>
00019 {
00020 };
00021 
00022 template <typename From, typename To>
00023 struct is_same_real
00024   : std::integral_constant<bool, std::is_same<From, To>::value && std::is_floating_point<To>::value>
00025 {
00026 };
00027 
00028 template <typename From, typename To>
00029 struct is_safe_integer_conversion
00030   : std::integral_constant<bool, is_integer<From>::value && is_integer<To>::value &&
00031                                      sizeof(From) < sizeof(To) &&
00032                                      std::is_signed<From>::value == std::is_signed<To>::value>
00033 {
00034 };
00035 
00036 template <typename T>
00037 struct is_convertible_type
00038   : std::integral_constant<bool, std::is_integral<T>::value || std::is_floating_point<T>::value ||
00039                                      std::is_same<T, bool>::value || std::is_same<T, char>::value ||
00040                                      std::is_same<T, std::string>::value ||
00041                                      std::is_same<T, SimpleString>::value || std::is_enum<T>::value>
00042 {
00043 };
00044 
00045 template <typename From, typename To>
00046 struct float_conversion : std::integral_constant<bool, std::is_floating_point<From>::value &&
00047                                                            std::is_floating_point<To>::value &&
00048                                                            !std::is_same<From, To>::value>
00049 {
00050 };
00051 
00052 template <typename From, typename To>
00053 struct unsigned_to_smaller_conversion
00054   : std::integral_constant<bool, is_integer<From>::value && is_integer<To>::value &&
00055                                      (sizeof(From) > sizeof(To)) && !std::is_signed<From>::value &&
00056                                      !std::is_signed<To>::value>
00057 {
00058 };
00059 
00060 template <typename From, typename To>
00061 struct signed_to_smaller_conversion
00062   : std::integral_constant<bool, is_integer<From>::value && is_integer<To>::value &&
00063                                      (sizeof(From) > sizeof(To)) && std::is_signed<From>::value &&
00064                                      std::is_signed<To>::value>
00065 {
00066 };
00067 
00068 //---------------------------
00069 template <typename From, typename To>
00070 struct signed_to_smaller_unsigned_conversion
00071   : std::integral_constant<bool, is_integer<From>::value && is_integer<To>::value &&
00072                                      sizeof(From) >= sizeof(To) && std::is_signed<From>::value &&
00073                                      !std::is_signed<To>::value>
00074 {
00075 };
00076 
00077 template <typename From, typename To>
00078 struct signed_to_larger_unsigned_conversion
00079   : std::integral_constant<bool, is_integer<From>::value && is_integer<To>::value &&
00080                                      sizeof(From) < sizeof(To) && std::is_signed<From>::value &&
00081                                      !std::is_signed<To>::value>
00082 {
00083 };
00084 
00085 template <typename From, typename To>
00086 struct unsigned_to_smaller_signed_conversion
00087   : std::integral_constant<bool, is_integer<From>::value && is_integer<To>::value &&
00088                                      (sizeof(From) >= sizeof(To)) && !std::is_signed<From>::value &&
00089                                      std::is_signed<To>::value>
00090 {
00091 };
00092 
00093 template <typename From, typename To>
00094 struct unsigned_to_larger_signed_conversion
00095   : std::integral_constant<bool, is_integer<From>::value && is_integer<To>::value &&
00096                                      sizeof(From) < sizeof(To) && !std::is_signed<From>::value &&
00097                                      std::is_signed<To>::value>
00098 {
00099 };
00100 
00101 template <typename From, typename To>
00102 struct floating_to_signed_conversion
00103   : std::integral_constant<bool, std::is_floating_point<From>::value && is_integer<To>::value &&
00104                                      std::is_signed<To>::value>
00105 {
00106 };
00107 
00108 template <typename From, typename To>
00109 struct floating_to_unsigned_conversion
00110   : std::integral_constant<bool, std::is_floating_point<From>::value && is_integer<To>::value &&
00111                                      !std::is_signed<To>::value>
00112 {
00113 };
00114 
00115 template <typename From, typename To>
00116 struct integer_to_floating_conversion
00117   : std::integral_constant<bool, is_integer<From>::value && std::is_floating_point<To>::value>
00118 {
00119 };
00120 
00121 template <typename From, typename To>
00122 inline void checkUpperLimit(const From& from)
00123 {
00124     if ((sizeof(To) < sizeof(From)) && (from > static_cast<From>(std::numeric_limits<To>::max())))
00125     {
00126         throw std::runtime_error("Value too large.");
00127     }
00128     else if (static_cast<To>(from) > std::numeric_limits<To>::max())
00129     {
00130         throw std::runtime_error("Value too large.");
00131     }
00132 }
00133 
00134 template <typename From, typename To>
00135 inline void checkUpperLimitFloat(const From& from)
00136 {
00137     if (from > std::numeric_limits<To>::max())
00138     {
00139         throw std::runtime_error("Value too large.");
00140     }
00141 }
00142 
00143 template <typename From, typename To>
00144 inline void checkLowerLimitFloat(const From& from)
00145 {
00146     if (from < -std::numeric_limits<To>::max())
00147     {
00148         throw std::runtime_error("Value too small.");
00149     }
00150 }
00151 
00152 template <typename From, typename To>
00153 inline void checkLowerLimit(const From& from)
00154 {
00155     if (from < std::numeric_limits<To>::min())
00156     {
00157         throw std::runtime_error("Value too small.");
00158     }
00159 }
00160 
00161 template <typename From, typename To>
00162 inline void checkTruncation(const From& from)
00163 {
00164     if (from != static_cast<From>(static_cast<To>(from)))
00165     {
00166         throw std::runtime_error("Floating point truncated");
00167     }
00168 }
00169 
00170 //----------------------- Implementation ----------------------------------------------
00171 
00172 template <typename SRC, typename DST>
00173 inline typename std::enable_if<!is_convertible_type<DST>::value, void>::type
00174 convertNumber(const SRC&, DST&)
00175 {
00176     static_assert(is_convertible_type<DST>::value, "Not convertible");
00177 }
00178 
00179 template <typename SRC, typename DST>
00180 inline EnableIf<std::is_same<bool, DST>> convertNumber(const SRC& from, DST& target)
00181 {
00182     target = (from != 0);
00183 }
00184 
00185 template <typename SRC, typename DST>
00186 inline EnableIf<std::is_same<SRC, DST>> convertNumber(const SRC& from, DST& target)
00187 {
00188     target = from;
00189 }
00190 
00191 template <typename SRC, typename DST>
00192 inline EnableIf<is_safe_integer_conversion<SRC, DST>> convertNumber(const SRC& from, DST& target)
00193 {
00194     target = static_cast<DST>(from);
00195 }
00196 
00197 template <typename SRC, typename DST>
00198 inline EnableIf<float_conversion<SRC, DST>> convertNumber(const SRC& from, DST& target)
00199 {
00200     checkTruncation<SRC, DST>(from);
00201     target = static_cast<DST>(from);
00202 }
00203 
00204 template <typename SRC, typename DST>
00205 inline EnableIf<unsigned_to_smaller_conversion<SRC, DST>> convertNumber(const SRC& from,
00206                                                                         DST& target)
00207 {
00208     checkUpperLimit<SRC, DST>(from);
00209     target = static_cast<DST>(from);
00210 }
00211 
00212 template <typename SRC, typename DST>
00213 inline EnableIf<signed_to_smaller_conversion<SRC, DST>> convertNumber(const SRC& from, DST& target)
00214 {
00215     checkLowerLimit<SRC, DST>(from);
00216     checkUpperLimit<SRC, DST>(from);
00217     target = static_cast<DST>(from);
00218 }
00219 
00220 template <typename SRC, typename DST>
00221 inline EnableIf<signed_to_smaller_unsigned_conversion<SRC, DST>> convertNumber(const SRC& from,
00222                                                                                DST& target)
00223 {
00224     if (from < 0)
00225     {
00226         throw std::runtime_error("Value is negative and can't be converted to signed");
00227     }
00228 
00229     checkUpperLimit<SRC, DST>(from);
00230     target = static_cast<DST>(from);
00231 }
00232 
00233 template <typename SRC, typename DST>
00234 inline EnableIf<signed_to_larger_unsigned_conversion<SRC, DST>> convertNumber(const SRC& from,
00235                                                                               DST& target)
00236 {
00237     if (from < 0)
00238     {
00239         throw std::runtime_error("Value is negative and can't be converted to signed");
00240     }
00241 
00242     target = static_cast<DST>(from);
00243 }
00244 
00245 template <typename SRC, typename DST>
00246 inline EnableIf<unsigned_to_larger_signed_conversion<SRC, DST>> convertNumber(const SRC& from,
00247                                                                               DST& target)
00248 {
00249     target = static_cast<DST>(from);
00250 }
00251 
00252 template <typename SRC, typename DST>
00253 inline EnableIf<unsigned_to_smaller_signed_conversion<SRC, DST>> convertNumber(const SRC& from,
00254                                                                                DST& target)
00255 {
00256     checkUpperLimit<SRC, DST>(from);
00257     target = static_cast<DST>(from);
00258 }
00259 
00260 template <typename SRC, typename DST>
00261 inline EnableIf<floating_to_signed_conversion<SRC, DST>> convertNumber(const SRC& from, DST& target)
00262 {
00263     checkLowerLimitFloat<SRC, DST>(from);
00264     checkLowerLimitFloat<SRC, DST>(from);
00265 
00266     if (from != static_cast<SRC>(static_cast<DST>(from)))
00267     {
00268         throw std::runtime_error("Floating point truncated");
00269     }
00270 
00271     target = static_cast<DST>(from);
00272 }
00273 
00274 template <typename SRC, typename DST>
00275 inline EnableIf<floating_to_unsigned_conversion<SRC, DST>> convertNumber(const SRC& from,
00276                                                                          DST& target)
00277 {
00278     if (from < 0)
00279     {
00280         throw std::runtime_error("Value is negative and can't be converted to signed");
00281     }
00282 
00283     checkLowerLimitFloat<SRC, DST>(from);
00284 
00285     if (from != static_cast<SRC>(static_cast<DST>(from)))
00286     {
00287         throw std::runtime_error("Floating point truncated");
00288     }
00289 
00290     target = static_cast<DST>(from);
00291 }
00292 
00293 template <typename SRC, typename DST>
00294 inline EnableIf<integer_to_floating_conversion<SRC, DST>> convertNumber(const SRC& from,
00295                                                                         DST& target)
00296 {
00297     checkTruncation<SRC, DST>(from);
00298     target = static_cast<DST>(from);
00299 }
00300 
00301 }   //end namespace details
00302 }   //end namespace details
00303 
00304 #endif   // CONVERT_IMPL_HPP


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