Search code examples
c++dllcpp-core-guidelines

How to use gsl narrow cast


I am trying to understand how to use gsl::narrow_cast instead of static_cast. I found here on stackoverflow a function that has a string as a parameter and returns true if all characters are ASCII (first 127 characters).

bool IsCleanString(const std::string& str)
{
    return !std::any_of(str.begin(), str.end(), [](char c) {
        return narrow_cast<unsigned char>(c) > 127;
    });
}

I have implemented this function in my code and I noticed Visual Studio suggests the use of either gsl::narrow or gsl::narrow_cast. My first question is how to use gsl functions? I have looked at other questions on the website and I haven't found one that tells how to even see the gsl class/library (I am building a dll) And the second question is what would be the correct syntax for this function, is it even necessary to change it in this case? Thanks.


Solution

  • The GSL was initially created as Microsoft's implementation of the C++ Core Guidelines. But this is not the only implementation of it. One other implementation is the (header-only) gsl-lite.

    gsl::narrow is a static_cast that checks if information is lost via the cast and will then throw an exception. Losing information means that casting back to the initial type will give a value different from the input.

    In practice this means that gsl::narrow<unsigned>(42) will just behave the same as static_cast, while gsl::narrow<unsigned>(-42) will throw. Another example would be gsl::narrow<int>(42.0) (works like static_cast) and gsl::narrow<int>(42.1) (exception). As gsl::narrow checks it's result, it could impact performance negatively e.g. when used inside hot loops.

    In cases where you want to lose information (e.g. binning) but want to mark this behavior (make it searchable in your code), you can use gsl::narrow_cast which is just a wrapper around static_cast (same syntax, same behavior).

    Both casts are introduced in the Core Guidelines here (ES.46).