Earlier quoted context omitted.
they easily can :) void test(int& y){} int main() { int* x = nullptr; test(*x); }
There is a difference between an API promissing that a value wont be null and a buggy program setting a null where it should not. A reference is only null if someone fucked up. As a programmer you can usually rely on a reference not being null and you couldn't do anything about it if it was anyway within the constraints of the language.
Enum class improvements for C++17, C++20 and C++23
71–80 of 121 posts
Re: Enum class improvements for C++17, C++20 and C++23
#72All that crap is the reason I never bother with enums in all these C like languages set_player_color(player, .RED); That should be the way to use them, it's concise and typesafe set_color(Color::RED); Why repeat yourself? It's one of the things I love about Swift and Zig int main() { using enum ComputeStatus; ComputeStatus s = NotEnoughMemory; } now you have polluted the scope.. C++ have lost the plot.. they understo…
computation_service.set_status(ComputeStatus::NotEnoughMemory);
system.set_state(SystemState::Failure);
is a lot clearer than computation_service.set_state(.NotEnoughMemory);
system.set_state(.Failure);
in my opinion. Both objects/structs/whatevers can have a state type of their own but the shorthand form does not indicate whether or not the two can be used interchangeably. As a workaround, you could rename the setter to set_computation_state and set_system_state but then you're just repeating yourself in a different manner that's not as precise.Re: Enum class improvements for C++17, C++20 and C++23
#73enum class Handle : uint32_t { Invalid = 0 }; Handle h { 42 }; // OK One of their examples demonstrates the number one issue for me with enums, which was not fixed with `enum class`. Since values outside the range of the type are valid, you are constantly needing to check for invalid values in any function that takes an enum [class]. Ruins any attempt at "parse, don't validate" style in c++ and completely ruins the "…
What the alternative? Let’s say you have a file, you parse a uint32_t, and you want to convert that into the Handle type. If the enum is closed how do you do it? Giant switch? That would break the fundamental principle that C++ abstractions are zero-cost.
Most enum use is served adequately by never letting in potentially invalid values from untrusted input; an enum variable that is set to an enum constant will necessarily have a valid value. "Decayed" primitive values, like a bitmask formed by bitwise operations between valid enum values, aren't normally intended to be re-ingested as enum values.
Re: Enum class improvements for C++17, C++20 and C++23
#74enum class Handle : uint32_t { Invalid = 0 }; Handle h { 42 }; // OK One of their examples demonstrates the number one issue for me with enums, which was not fixed with `enum class`. Since values outside the range of the type are valid, you are constantly needing to check for invalid values in any function that takes an enum [class]. Ruins any attempt at "parse, don't validate" style in c++ and completely ruins the "…
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 us…
If you could do:
my_enum_type foo(std::vector& 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.
Re: Enum class improvements for C++17, C++20 and C++23
#75Earlier quoted context omitted.
It wasn't unfixed in C++17. The problem existed before C++17. This is valid code in C++11: enum class Foo : int { Invalid = 0 }; Foo f = Foo(5); In C++11, this compiles with Foo(5) but not Foo{5}. In C++17, this compiles with both Foo(5) and Foo{5}.
IIRC for a brief period GCC considered values outside of the enumeration as UB and heavily optimized according to this. At some point this interpretetion made it as far as at least a draft standard. Then it got reverted as it went against decades of common usages and instead the opposite was made explicit in the standard. Making it UB for enum classes was considered, but the strongly typeded alias use case was consid…
Re: Enum class improvements for C++17, C++20 and C++23
#76Earlier quoted context omitted.
Probably not too much work to add and then also build a JSONLD @context from all of the ~ message structs. :Thing > https://schema.org/name , :URL , :identifier and subclasses Thing > Intangible > Enumeration: https://schema.org/Enumeration
Adding reflection will be simple and backwards compatible with existing code as it would only come into play when someone hasn't manually mapped a type. This leaves the cases where reflection doesn't work(private member variables) still workable too. Haven't looked at JSONLD much, but it seems like it could be added but would be a library above I think. Extracting the mappings is already doable and is done in the JSO…
include
std::string daw::json::to_json_schema( "identifier", "title" );
From https://westurner.github.io/hnlog/#comment-38526588 :> SHACL is used for expressing integrity constraints on complete data, while OWL allows inferring implicit facts from incomplete data; SHACL reasoners perform validation, while OWL reasoners do logical inference.
- "Show HN: Pg_jsonschema – A Postgres extension for JSON validation" https://news.ycombinator.com/item?id=32186878 re: json-ld-schema, which bridges JSONschema and SHACL for JSONLD
Re: Enum class improvements for C++17, C++20 and C++23
#77Earlier quoted context omitted.
an event loop often wants an event type enum that has defined values for internal events and then everything out of range means pass onto the users handler. There are other variations where you need to pass an enum value without caring what it mean.
This isn't rocket science once you have sum types. enum Event { System(SystemEvent), User(T), }
Anyway, the point of what gp describes is to do this in a single integer without overhead so a naive sum type is not the solution.
Re: Enum class improvements for C++17, C++20 and C++23
#78enum class Handle : uint32_t { Invalid = 0 }; Handle h { 42 }; // OK One of their examples demonstrates the number one issue for me with enums, which was not fixed with `enum class`. Since values outside the range of the type are valid, you are constantly needing to check for invalid values in any function that takes an enum [class]. Ruins any attempt at "parse, don't validate" style in c++ and completely ruins the "…
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 us…
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.
Re: Enum class improvements for C++17, C++20 and C++23
#79Earlier quoted context omitted.
There is a difference between an API promissing that a value wont be null and a buggy program setting a null where it should not. A reference is only null if someone fucked up. As a programmer you can usually rely on a reference not being null and you couldn't do anything about it if it was anyway within the constraints of the language.
In the same way, an `enum class` variable's value being outside of the set defined in the `enum class` is also a fuckup.
You could design a language feature where integer to enum is checked, but that's not enum.
Enum classes already add scoping, forbid implicit conversions and allow explicit underlying types. Those are pure extensions. Making undeclared values invalid or UB would be very surprising to people used to normal enums.
Re: Enum class improvements for C++17, C++20 and C++23
#80enum class Handle : uint32_t { Invalid = 0 }; Handle h { 42 }; // OK One of their examples demonstrates the number one issue for me with enums, which was not fixed with `enum class`. Since values outside the range of the type are valid, you are constantly needing to check for invalid values in any function that takes an enum [class]. Ruins any attempt at "parse, don't validate" style in c++ and completely ruins the "…
The main difference between old ("unscoped") and new ("scoped") enums, besides dropping implicit conversions from/to integral types, is the scope of the named constants. With unscoped enums, the constants are in the surrounding scope, which means that constants with the same name but of different enum types collide with each other. One solution is to wrap them in a dummy struct or class (`struct Foo { enum Bar { baz…
Except bitwise operations of orign enum values yields the underlying type and not an enum value. And for enum classes the operators don't exist at all. So you need to write custom operators(or manual casts) for this use case anyway so you might as well go all the way and write a proper typed bitset type instead of abusing enums. Allowing this for old enums makes sense for C compat but that doesn't mean enum class couldn't have been stricter.