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


ros_type_introspection
Author(s): Davide Faconti
autogenerated on Sun Oct 1 2017 02:54:53