/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright 2011 Danny Robson */ #ifndef __UTIL_TYPES_CASTS_HPP #define __UTIL_TYPES_CASTS_HPP #include "../debug.hpp" #include #include //----------------------------------------------------------------------------- namespace detail { template T _sign_cast (const typename std::enable_if::value && std::is_signed::value, V>::type v) { CHECK_GE (v, 0); return static_cast (v); } template T _sign_cast (const typename std::enable_if::value && std::is_unsigned::value, V>::type v) { CHECK_LT (v, std::numeric_limits::max () / 2); return static_cast (v); } template T _sign_cast (const typename std::enable_if::value, V>::type v) { return 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 (const V v) { return detail::_sign_cast(v); } ///---------------------------------------------------------------------------- /// assert if the value cannot be cast loslessly from U to T, else return the /// converted value.Note: this is only a debug-time check and is compiled out /// in optimised builds. template T trunc_cast (U u) { auto t = static_cast (u); if (u == u) CHECK_EQ (t, u); else CHECK_NEQ (t, t); return t; } ///---------------------------------------------------------------------------- /// assert if the value is not a pointer to a subclass of T, else return the /// converted value. Note: this is only a debug-time check and is compiled out /// in optimised builds. template T* known_cast (V *v) { CHECK (dynamic_cast (v)); return static_cast (v); } //----------------------------------------------------------------------------- template T& known_cast (V &v) { CHECK_NOTHROW (dynamic_cast (v)); return static_cast (v); } #endif