microsoft / GSL

Guidelines Support Library

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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:

Exception

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!