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:
parent
d3c98d479e
commit
6910ef10b9
46
types.hpp
46
types.hpp
@ -1,6 +1,8 @@
|
||||
#ifndef __TYPES_HPP
|
||||
#define __TYPES_HPP
|
||||
|
||||
#include "enable_if.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <limits>
|
||||
@ -106,28 +108,38 @@ template <> struct sign_types <uint64_t> {
|
||||
};
|
||||
|
||||
|
||||
/// Safely cast a numeric type to its signed comparison, aborting if the
|
||||
/// result is not representable.
|
||||
template <typename T>
|
||||
typename sign_types<T>::with_sign
|
||||
sign_cast (const typename sign_types<T>::without_sign 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);
|
||||
}
|
||||
|
||||
|
||||
/// Safely cast a numeric type to its unsigned comparison, aborting if the
|
||||
/// result is not representable.
|
||||
template <typename T>
|
||||
typename sign_types<T>::without_sign
|
||||
sign_cast (const typename sign_types<T>::with_sign v)
|
||||
namespace detail {
|
||||
template <typename T, typename V>
|
||||
T
|
||||
_sign_cast (typename enable_if<sizeof(T) == sizeof(V) &&
|
||||
std::is_unsigned<T>::value &&
|
||||
std::is_signed<V>::value, V>::type v)
|
||||
{
|
||||
check_hard (v >= 0);
|
||||
return static_cast <typename sign_types<T>::without_sign> (v);
|
||||
return static_cast<T> (v);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, typename V>
|
||||
T
|
||||
_sign_cast (typename enable_if<sizeof(T) == sizeof(V) &&
|
||||
std::is_signed<T>::value &&
|
||||
std::is_unsigned<V>::value, V>::type v)
|
||||
{
|
||||
check_hard (v < std::numeric_limits<V>::max () / 2);
|
||||
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
|
||||
template <typename T, size_t N>
|
||||
size_t elems(T (&)[N])
|
||||
|
Loading…
Reference in New Issue
Block a user