diff --git a/types.hpp b/types.hpp index 2f823aaa..2bc84e3f 100644 --- a/types.hpp +++ b/types.hpp @@ -1,6 +1,8 @@ #ifndef __TYPES_HPP #define __TYPES_HPP +#include "enable_if.hpp" + #include #include #include @@ -106,27 +108,37 @@ template <> struct sign_types { }; -/// Safely cast a numeric type to its signed comparison, aborting if the -/// result is not representable. -template -typename sign_types::with_sign -sign_cast (const typename sign_types::without_sign v) -{ - check_hard (v <= std::numeric_limits::without_sign>::max () >> 1); - return static_cast ::with_sign> (v); -} +namespace detail { + template + T + _sign_cast (typename enable_if::value && + std::is_signed::value, V>::type v) + { + check_hard (v >= 0); + return static_cast (v); + } -/// Safely cast a numeric type to its unsigned comparison, aborting if the -/// result is not representable. -template -typename sign_types::without_sign -sign_cast (const typename sign_types::with_sign v) -{ - check_hard (v >= 0); - return static_cast ::without_sign> (v); + template + T + _sign_cast (typename enable_if::value && + std::is_unsigned::value, V>::type v) + { + check_hard (v < std::numeric_limits::max () / 2); + return static_cast (v); + } } +/// Safely cast a numeric type to its (un)signed counterpart, aborting if the +/// dynamically checked result is not representable. May be optimised out if +/// NDEBUG is defined. +template +T +sign_cast (V v) + { return detail::_sign_cast(v); } + /// Returns the number of elements of a statically allocated array template