1

I'm reviewing a lot of code where I need to ensure there are no static_cast (or any cast) calls on variables that could be out of range of the enum class that is being cast to. Ideally I'd be able to receive a warning or have some way to detect code that is casting from, for example, an int when the enum class in question has an underlying type of unsigned char.

enum class some_enum_class : unsigned char
{
    SomeVal,
};
int BadVal = 1000;
auto EnumVar = static_cast<some_enum_class>(BadVal); //Trigger Warning!

Is there any way to accomplish this? (hopefully in MSVC?)

GLJeff
  • 139
  • 10
  • 2
    You can write your own casting function. You can compare the template arguments to check if the first is the same as the second's underlying type with `std::underlying_type`. It won't keep anyone from using `static_cast` but it will detect mistakes if the developer uses the casting function. – François Andrieux Jan 04 '23 at 20:16
  • Eljay, changed to 1000 to make it an obvious problem Fran, I'm changing existing code. If I could overload static_cast that would work, but having a custom casting function does not help. – GLJeff Jan 04 '23 at 20:20
  • There is no other way except for maybe writing clang-tidy plugin. Really what you should do is search all suspicious `static_cast`s in your project and replace them with your function that has `static_assert(std::is_same_v, IntType>)` in it. – Osyotr Jan 04 '23 at 20:24
  • I don't think there's a way to do that if `static_assert` is happening, cast already means that you want the value of this type and nothing else. Custom cast like other commenter suggested or with C++17 you can use [direct list initialisation](https://en.cppreference.com/w/cpp/language/enum#enum_relaxed_init_cpp17) to ensure no narrowing conversion occurs (gcc emits a warning, clang and MSVC an error). – Yksisarvinen Jan 04 '23 at 20:29

1 Answers1

1

Doing your own casting function can help you, you can wrap the const_cast function using concepts and constraints of c++20 which specifies the requirements on template arguments. And for example clang tidy recognize it and throw a warning before any compilation.

#include <iostream>
#include <type_traits>

template<typename T, typename NewType>
concept isConvertible = std::is_convertible<NewType, T>::value;

template<typename T, typename NewType>
static NewType constraint_static_cast(T t)requires isConvertible<NewType, T>{
    return static_cast<NewType>(t);
}

int main(){
    enum class SomeEnumClass : unsigned char
    {
        SomeValue,
    };
    int bad_value = 1000;
    auto EnumVar = constraint_static_cast<int, SomeEnumClass>(bad_value); //Trigger Warning!
    auto EnumVar = constraint_static_cast<int, bool>(bad_value); //Work because of the concept
}
jdenozi
  • 212
  • 1
  • 11