Exception when using gsl::narrow with BYTE.
ajtruckle opened this issue · comments
This is not a bug in GSL. But I appreciate guidance please.
Based on code analysis I now have this code:
if (psColumnData->sActionListInfo.byCustomIndex != gsl::narrow<BYTE>(-1))
This raises an exception about different signed matches. I realize thet BYTE
is defined as unsigned char
so I have a missmatch.
Previously I had:
if (psColumnData->sActionListInfo.byCustomIndex != static_cast<BYTE>(-1))
When using static_cast
the value returned is 255
(I think) and by design that is fine for my code. Has been for years. Must I ignore the gsl warning and leave it as static_cast
or is there another gsl cast I can use?
Hi @ajtruckle,
Can you please provide some clarification on the following points?
- what is the type of
psColumnData->sActionListInfo.byCustomIndex
? - the snippet of code that you previously had is the same as the snippet of code that you now have (typo?)
- what is the exception message that you are seeing?
Thanks,
Dmitry
1/ It is:
BYTE byCustomIndex;
(which in turn is typedef unsigned char BYTE;
according to the SDK).
2/ That was a typo. :) It meant to use static_cast
.
It throws here:
// narrow() : a checked version of narrow_cast() that throws if the cast changed the value
template <class T, class U, typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr>
// clang-format off
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // TODO: MSVC /analyze does not recognise noexcept(false)
// clang-format on
constexpr T narrow(U u) noexcept(false)
{
constexpr const bool is_different_signedness =
(std::is_signed<T>::value != std::is_signed<U>::value);
const T t = narrow_cast<T>(u);
if (static_cast<U>(t) != u || (is_different_signedness && ((t < T{}) != (u < U{}))))
{
throw narrowing_error{};
}
return t;
}
Does that help? If I run it in debug mode:
So there is no error message. It is just the fact that I am casting a negative value (-1
) to BYTE
which is unsigned by design.
I do it elsewhere in my program (eg. (UINT)-1
). So that would cause the same issue if I tried using gsl::narrow
.
Hi @ajtruckle,
Thanks for the clarification.
gsl::narrow<T>(x)
will behave as static_cast<T>(x)
if static_cast<T>(x) == x
, otherwise, it raises the error you are seeing. Because static_cast<unsigned char>(-1)
will wrap, as you pointed out, the error is expected.
If you want your behavior to stay as it was previously, you can use gsl::narrow_cast
, which is equivalent in behavior static_cast
, but expresses a clearer intent.
Thanks,
Dmitry
Fabulous. Using gsl::narrow_cast
works fine. No exception!