diff --git a/include/behaviortree_cpp/utils/convert_impl.hpp b/include/behaviortree_cpp/utils/convert_impl.hpp index 7aef50259..dffe17c98 100644 --- a/include/behaviortree_cpp/utils/convert_impl.hpp +++ b/include/behaviortree_cpp/utils/convert_impl.hpp @@ -13,6 +13,7 @@ #pragma once #include +#include #include "simple_string.hpp" #undef max @@ -88,9 +89,41 @@ inline void checkLowerLimit(const From& from) template inline void checkTruncation(const From& from) { - if(from != static_cast(static_cast(from))) + // Handle integer to floating point + if constexpr(std::is_integral_v && std::is_floating_point_v) { - throw std::runtime_error("Floating point truncated"); + // Check if value can be represented exactly in the target type + To as_float = static_cast(from); + From back_conv = static_cast(as_float); + if(back_conv != from) + { + throw std::runtime_error("Loss of precision in conversion to floating point"); + } + } + // Handle floating point to integer + if constexpr(std::is_floating_point_v && std::is_integral_v) + { + if(from > static_cast(std::numeric_limits::max()) || + from < static_cast(std::numeric_limits::lowest()) || + from != std::nearbyint(from)) + { + throw std::runtime_error("Invalid floating point to integer conversion"); + } + } + // Handle other conversions + else + { + if(from > static_cast(std::numeric_limits::max()) || + from < static_cast(std::numeric_limits::lowest())) + { + throw std::runtime_error("Value outside numeric limits"); + } + To as_target = static_cast(from); + From back_to_source = static_cast(as_target); + if(from != back_to_source) + { + throw std::runtime_error("Value truncated in conversion"); + } } }