New sign_cast implementation using SFINAE

* Uses enable_if to guarantee same size types for argument/return
* Uses type_traits to check signedness for specialisation
This commit is contained in:
Danny Robson 2011-07-05 22:53:03 +10:00
parent d3c98d479e
commit 6910ef10b9

View File

@ -1,6 +1,8 @@
#ifndef __TYPES_HPP #ifndef __TYPES_HPP
#define __TYPES_HPP #define __TYPES_HPP
#include "enable_if.hpp"
#include <cstdint> #include <cstdint>
#include <string> #include <string>
#include <limits> #include <limits>
@ -106,27 +108,37 @@ template <> struct sign_types <uint64_t> {
}; };
/// Safely cast a numeric type to its signed comparison, aborting if the namespace detail {
/// result is not representable. template <typename T, typename V>
template <typename T> T
typename sign_types<T>::with_sign _sign_cast (typename enable_if<sizeof(T) == sizeof(V) &&
sign_cast (const typename sign_types<T>::without_sign v) std::is_unsigned<T>::value &&
{ std::is_signed<V>::value, V>::type v)
check_hard (v <= std::numeric_limits<typename sign_types<T>::without_sign>::max () >> 1); {
return static_cast <typename sign_types<T>::with_sign> (v); check_hard (v >= 0);
} return static_cast<T> (v);
}
/// Safely cast a numeric type to its unsigned comparison, aborting if the template <typename T, typename V>
/// result is not representable. T
template <typename T> _sign_cast (typename enable_if<sizeof(T) == sizeof(V) &&
typename sign_types<T>::without_sign std::is_signed<T>::value &&
sign_cast (const typename sign_types<T>::with_sign v) std::is_unsigned<V>::value, V>::type v)
{ {
check_hard (v >= 0); check_hard (v < std::numeric_limits<V>::max () / 2);
return static_cast <typename sign_types<T>::without_sign> (v); return static_cast<T> (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 <typename T, typename V>
T
sign_cast (V v)
{ return detail::_sign_cast<T,V>(v); }
/// Returns the number of elements of a statically allocated array /// Returns the number of elements of a statically allocated array
template <typename T, size_t N> template <typename T, size_t N>