Live data from Hacker News

Enum class improvements for C++17, C++20 and C++23

cppstories.com

21–30 of 121 posts

Re: Enum class improvements for C++17, C++20 and C++23

#21
post #7

Odd that it says auto value = std::to_underlying(p); // C++23 is "more expressive" than uint8_t value = static_cast (Permissions::Read); The latter seems clearly more expressive, not less. You could tighten it up a bit by using auto on the LHS instead of the redundant uint8_t. In the former I don't know what's going on and I have to go read another header to figure out the type of `value`.

And when the enum values don't fit into the uint8_t? If you want the enum variables constrained to an integer type do that in the enum definition itself. The compiler can then bark at you when you add a member outside the range.

Re: Enum class improvements for C++17, C++20 and C++23

#22
post #11

Earlier quoted context omitted.

The expressibility of a language is what can be expressed in it, not what it can express to you. This additional feature allows you to express this projection without being explicit.

I disagree. Any language can tell the computer what to do. The quality of a good language is that it also clearly communicates to human readers.

That's true, but unrelated to the common usage of the word "expressiveness" when talking about programming languages. There's often a tradeoff between expressiveness and the thing you're talking about, which I'll call clarity. For example, macros increase expressiveness but decrease clarity. In Racket (or other lisps), you can define a macro `(my-let x 17 (+ x 1)) -> 18`. This is expressive, as most other languages don't let you define binding constructs so easily, but also bad for clarity because `my-let` doesn't look different than a regular function, so it's hard to tell at a glance that it's doing something a function could never do.

Re: Enum class improvements for C++17, C++20 and C++23

#23
post #11

Earlier quoted context omitted.

The expressibility of a language is what can be expressed in it, not what it can express to you. This additional feature allows you to express this projection without being explicit.

I disagree. Any language can tell the computer what to do. The quality of a good language is that it also clearly communicates to human readers.

I think you are thinking of the concept of "explicitness" not "expressiveness".

Re: Enum class improvements for C++17, C++20 and C++23

#24

Union, inheritance, dynamic_cast, enum class, std::variant... when all we needed all along was proper sum types.

My guess currently is that C++ 29 will get some sort of pattern matching. It's too big a feature to board the C++ 26 train in autumn 2024 and there's nowhere close to consensus on how it should work or how it's spelled yet.

So, assume C++ 29 has pattern matching. That causes people to attempt various idiomatic constructions from languages which always had pattern matching, and of course they're all rather awkward in C++. I think that realisation might point towards an actual language sum type, possibly via abortive attempts to "fix" matching and/or some of the pseudo-sum types provided by the C++ stdlib. So then you'd expect proposals in C++ 32 or C++ 35.

Re: Enum class improvements for C++17, C++20 and C++23

#25
post #9

enum 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 "…

IMO that's the typical experience with many of the features in modern C++ standards. You read about a really neat useful thing they added, something that seems to provide a safe and practical way to overcome a shortcoming in the language. You may even get a little excited...until you try to actually use it and realize its full of new footguns and weird limitations

Re: Enum class improvements for C++17, C++20 and C++23

#26

Union, inheritance, dynamic_cast, enum class, std::variant... when all we needed all along was proper sum types.

Sum types do not replace all the things you listed. Even Rust has different concepts for many of those.

I don't think they're complaining that Sum types are equivalent to any or all of those things, but rather that what they wanted was Sum types and C++ has given them all this other stuff claiming it will solve their problem, instead of a Sum type which does solve the problem.

If what I need is a bookshelf then it's true that a wardrobe, a cardboard box, a Kindle, and a shredder are all different things and a bookshelf would not substitute for any of them, but giving me the wardrobe, cardboard box, Kindle and shredder doesn't solve my problem, I needed a bookshelf.

Re: Enum class improvements for C++17, C++20 and C++23

#27
post #20
post #16

Earlier quoted context omitted.

Well, apparently it was fixed with `enum class`… until it was un fixed in C++17 for unfathomable reasons. It’s honestly crazy that C++ doesn’t have simple exhaustiveness-checked enums. The obvious actual solution for the valid use case of deserializing an enum from an integer would be something like template std::optional from_underlying(std::underlying_type ) requires(std::is_enum_v )

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),
    }

Re: Enum class improvements for C++17, C++20 and C++23

#28

Earlier quoted context omitted.

Sum types do not replace all the things you listed. Even Rust has different concepts for many of those.

I don't think they're complaining that Sum types are equivalent to any or all of those things, but rather that what they wanted was Sum types and C++ has given them all this other stuff claiming it will solve their problem, instead of a Sum type which does solve the problem. If what I need is a bookshelf then it's true that a wardrobe, a cardboard box, a Kindle, and a shredder are all different things and a bookshelf…

It makes no sense to mention dyanmic_cast or inheritance (clearly referencing virtual functions here) when languages with sum types also have equivalents. It just shows a misunderstanding of how these features are used.

I don't think I've ever seen an analogy contribute to a discussion, and yours is no exception.

Re: Enum class improvements for C++17, C++20 and C++23

#29
post #7

Odd that it says auto value = std::to_underlying(p); // C++23 is "more expressive" than uint8_t value = static_cast (Permissions::Read); The latter seems clearly more expressive, not less. You could tighten it up a bit by using auto on the LHS instead of the redundant uint8_t. In the former I don't know what's going on and I have to go read another header to figure out the type of `value`.

The former is more expressive because it doesn't require a template to manually deduce the underlying type of an enum as `static_cast>(Permissions::Read)`

Re: Enum class improvements for C++17, C++20 and C++23

#30
post #25
post #9

enum 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 "…

IMO that's the typical experience with many of the features in modern C++ standards. You read about a really neat useful thing they added, something that seems to provide a safe and practical way to overcome a shortcoming in the language. You may even get a little excited...until you try to actually use it and realize its full of new footguns and weird limitations

Yes, you read about std::variant on a blog and think that it is a sum type. Then you try it out and realize that it's a thin (type-safe) wrapper over tagged unions that is at least three times slower and has about 5 unreadable alternatives that replace simple switch statements.

Then you find out that members of a "variant" are not really variant members but just the individual types that can be assigned to a union. For example, assigning to a non-const reference does not work (and obviously cannot work once you realize that std::variant is just syntax sugar over a tagged union).

Most of these new additions since C++11 are just leaky abstractions and wrappers.

Post reply on HN