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
|
#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>
|
||||||
|
Loading…
Reference in New Issue
Block a user