c++ - Well defined narrowing cast -
i'm trying come narrowing cast (a general solution) gracefully ignores lost data. in visual studio, narrowing cast loses data triggers "run-time check failure #1". not want turn off, instead i'm trying implement narrow_cast
gracefully narrowing casts , wouldn't trigger run time check.
visual studio suggests:
char c = (i & 0xff);
so started this, , came ugly solution:
template< typename t > struct narrow_mask { static const t value = t(0xffffffffffffffff); }; template <typename t, typename u> t narrow_cast(const u& a) { return static_cast<t>(a & narrow_mask<t>::value ); }
while works (vs seems fine losing data on constants), it's neither complete (no support non integral data), nor correct (i think not work correctly signed values).
any suggestions better solution, or better narrow_mask implementation?
edit: in face of comments question vs specific, checked standard document, , seems result of narrowing static_cast
implementation dependant. hence, question can nicer stated creating well-defined (ergo, not implementation dependant) narrowing cast. not care specifics of result value, long it's defined , dependant on type (not return 0
).
here's 1 version uses little bit of c++11. if don't have access constexpr
, can delete it. if don't have access std::make_unsigned
, it's possible implement own. if don't have std::enable_if
, might able use boost's (or make own). works both signed , unsigned types, positive , negative values. update: updated work floating point types (and floating point integral, , vice versa).
#include <type_traits> // integer type integer type template <typename to, typename from> constexpr typename std::enable_if<std::is_integral<from>::value && std::is_integral<to>::value, to>::type narrow_cast(const from& value) { return static_cast<to>(value & (static_cast<typename std::make_unsigned<from>::type>(-1))); } // these next 3 versions, you'd best off locally disabling compiler warning // there isn't magic can when floating point types invovled // floating point type floating point type template <typename to, typename from> constexpr typename std::enable_if<std::is_floating_point<from>::value && std::is_floating_point<to>::value, to>::type narrow_cast(const from& value) { // best can here direct cast return static_cast<to>(value); } // integer type floating point type template <typename to, typename from> constexpr typename std::enable_if<std::is_integral<from>::value && std::is_floating_point<to>::value, to>::type narrow_cast(const from& value) { // best can here direct cast return static_cast<to>(value); } // floating point type integer type template <typename to, typename from> constexpr typename std::enable_if<std::is_floating_point<from>::value && std::is_integral<to>::value, to>::type narrow_cast(const from& value) { // best can here direct cast return static_cast<to>(value); }
Comments
Post a Comment