有什么方法可以在 T 的类型不是 some_enum_class 的基础类型的情况下获得 static_cast<some_enum_class>(T) 的警告?

Any way to get a warning for static_cast<some_enum_class>(T) where T's type isn't the underlying type of some_enum_class?

提问人:GLJeff 提问时间:1/5/2023 最后编辑:GLJeff 更新时间:1/5/2023 访问量:89

问:

我正在审查很多代码,在这些代码中,我需要确保没有对可能超出被强制转换的枚举类范围的变量进行static_cast(或任何强制转换)调用。理想情况下,我能够收到警告,或者有某种方法来检测从(例如,当所讨论的枚举类具有无符号字符的基础类型时)从 int 转换的代码。

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

有什么方法可以做到这一点吗?(希望在 MSVC 中?

C++ C++20 静态强制转换 枚举类

评论

2赞 François Andrieux 1/5/2023
您可以编写自己的转换函数。您可以将模板参数与 进行比较,以检查第一个参数是否与第二个参数的基础类型相同。它不会阻止任何人使用,但如果开发人员使用投射功能,它会检测到错误。std::underlying_typestatic_cast
0赞 GLJeff 1/5/2023
Eljay,更改为 1000 以使其成为一个明显的问题 Fran,我正在更改现有代码。如果我能重载static_cast那会起作用,但拥有自定义投射功能无济于事。
0赞 Osyotr 1/5/2023
除了编写 clang-tidy 插件之外,别无他法。实际上,您应该做的是搜索项目中所有可疑的 s,并将它们替换为其中的函数。static_caststatic_assert(std::is_same_v<std::underlying_type_t<EnumType>, IntType>)
0赞 Yksisarvinen 1/5/2023
如果发生这种情况,我认为没有办法做到这一点,cast 已经意味着你想要这种类型的值,仅此而已。自定义转换,就像其他评论者建议的那样,或者使用 C++17,您可以使用直接列表初始化来确保不会发生缩小转换(gcc 发出警告、clang 和 MSVC 错误)。static_assert

答:

1赞 jdenozi 1/5/2023 #1

做你自己的强制转换函数可以帮助你,你可以使用概念和约束来包装函数,这些概念和约束指定了对模板参数的要求。 例如,clang tidy,识别它并在任何编译之前发出警告。const_castc++20

#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
}