5 ms·
That's by design. Consider mapping a file or reinterpret casting a network buffer that contains a structure with such an enum: if has been written by a differen
by gpderetta 2y ago
That's by design. Consider mapping a file or reinterpret casting a network buffer that contains a structure with such an enum: if has been written by a different version of an application, the possible enum values might be different. That was considered, among other thing, an important use case to support.
You can easily build your own safe enum on top of you really want.
Edit: someone else pointed out the bitmask use case else thread. Strongly typed integrals is also a common use case.
- maccard 2y agoYou can justify the escape hatches for every feature in C++. The problem is that we eschew sensible defaults to handle the edge cases. Without going into a rust war, I think rust's unsafe is a great way to handle this - for 99% of use cases, you _really_ don't want to put an invalid enum value in there. But, in the number of cases where you do, you should have an escape hatch to do so. If you could do: my_enum_type foo(std::vector<char>& buf, int& offset) { // bounds check omitted for brevity // return my_enum_type{buf{offset++]}; // outside an unsafe-style block would cause a compile error, or a throwing constructor. TBD std::unsafe { return my_enum_type{buf[offset++]}; } } you would reduce the possible impact areas to places where you explicitly want to do dangerous stuff. Instead we end up with a feature that is a "zero cost abstraction" which just pushes the bookkeeping onto the user - every switch statemeent needs to handle the case where someone has passed in 42.
- gpderetta 2y agoI assure you I'm very critical of C++ bad defaults. But in this case I think it was the right solution. There were three options: 1. make invalid values UB. 2. make invalid values non-representable by enforcing checks. 3. enum class is just a strong integer typedef with named constants. Luckily 1 was reject: already too much UB. 2 would require runtime checking and was not considred viable by many; also it would prevent a lot of useful cases. 3 was the remaining option and was consistent with existing enum usage.
- account42 2y agoI don't think reinterpret casting enums is something that should be encouraged and uncovering such points where unexpected values can be introduced is exactly the point of having a strict enum. Just because putting random values into the enum isn't itself undefined behavior doesn't mean that your program isn't going to blow up later on. Bitmask enums are also a hack and the better solution is to have different types for the individual flags (an enum) as well as a type for combinations of flags (custom type built around an integer). Yes, these are existing uses but when enum class was designed there were no existing usages for that.
- gpderetta 2y agoHaving tried the solution with a separate type for the bitset as opposed to the enum itself, in my experience the complexity it is just not worth the improvement. > but when enum class was designed there were no existing usages for that. IIRC diverging from standard enum was considred, but rejected as deemed a surprising change in behaviour.