[HN Gopher] Enum class improvements for C++17, C++20 and C++23
       ___________________________________________________________________
        
       Enum class improvements for C++17, C++20 and C++23
        
       Author : ibobev
       Score  : 50 points
       Date   : 2024-08-04 20:09 UTC (2 hours ago)
        
 (HTM) web link (www.cppstories.com)
 (TXT) w3m dump (www.cppstories.com)
        
       | fouronnes3 wrote:
       | Union, inheritance, dynamic_cast, enum class, std::variant...
       | when all we needed all along was proper sum types.
        
         | searealist wrote:
         | Sum types do not replace all the things you listed. Even Rust
         | has different concepts for many of those.
        
         | tialaramex wrote:
         | 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.
        
       | westurner wrote:
       | Speaking of enums, what's a better serialization framework for
       | C++ like Serde in Rust, and then what about Linked Data support
       | and of course also form validation.
       | 
       | Linked Data triples have (subject, predicate, object) and quads
       | have (graph, subject, predicate, object).
       | 
       | RDF has URIs for all Subjects and Predicates.
       | 
       | RDF Objects may be URIs or literal values like xsd:string,
       | xsd:float64, xsd:int (32bit signed value), xsd:integer, xsd:long,
       | xsd:time, xsd:dateTime, xsd:duration.
       | 
       | RDFS then defines Classes and Properties, identified by string
       | URIs.
       | 
       | How best to get from an Enum with (type,attr, {range of values})
       | to an rdfs:range definition in a schema with a URI prefix?
       | 
       | Python has dataclasses which is newer than attrs, but serde also
       | emits Python pickles
        
         | beached_whale wrote:
         | re Serde: If you want JSON,
         | https://github.com/beached/daw_json_link is about as close as
         | we can get. It interop's well with the reflection(or like)
         | libraries such as Boost Describe or Boost PFR and will work
         | well with std reflection when it is available.
        
           | westurner wrote:
           | 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
        
         | pjmlp wrote:
         | So far, most people would use whatever is provided alongside
         | the frameworks they are already using for their application.
         | 
         | Since the 90's, Turbo Vision, OWL, MFC, CSet++, Tools.h++, VCL,
         | ATL, PowerPlant, Qt, Boost, JUCE, Unreal, CryEngine,....
         | 
         | Maybe if reflection does indeed land into C++26, something
         | might be more universally adopted.
        
           | westurner wrote:
           | "Reflection for C++26" (2024)
           | https://news.ycombinator.com/item?id=40836594
           | 
           | Wt:Dbo years ago but that's just objects to and from SQL,
           | it's not linked data schema or fast serialization with e.g.
           | Arrow.
           | 
           | There should be easy URIs for Enums, which I guess map most
           | closely to the rdfs:range of an rdfs:Property. Something
           | declarative and/or extracted by another source parser would
           | work. To keep scheme definitions DRY
        
       | James_K wrote:
       | > C++20 introduced the `using enum` syntax, which enhances the
       | usability of enums
       | 
       | Out of context, this is a very funny thing to say.
        
       | jeffbee wrote:
       | Odd that it says                 auto value =
       | std::to_underlying(p); // C++23
       | 
       | is "more expressive" than                 uint8_t value =
       | static_cast<uint8_t>(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`.
        
         | CarpaDorada wrote:
         | 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.
        
           | jeffbee wrote:
           | 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.
        
             | rileymat2 wrote:
             | I think expressiblity is trickier than that. You can think
             | in a language with an imperative mindset where you are
             | describing what to do, or another with a declarative
             | mindset.
        
             | justinpombrio wrote:
             | 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.
        
             | dcsommer wrote:
             | I think you are thinking of the concept of "explicitness"
             | not "expressiveness".
        
         | frozenport wrote:
         | You're repeating the type and hoping it doesn't change when you
         | really just wanted the value.
        
         | kevin_thibedeau wrote:
         | 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.
        
       | lpribis wrote:
       | 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 "type safety" which c++ people
       | are always going on about.
        
         | Sharlin wrote:
         | 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<E>       std::optional<E>
         | from_underlying(std::underlying_type<E>)
         | requires(std::is_enum_v<E>)
        
           | bluGill wrote:
           | 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.
        
         | MawKKe wrote:
         | 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
        
       | wordofx wrote:
       | I don't feel like it's an improvement. Personally prefer the
       | explicit enum usage.
        
       | citizen_friend wrote:
       | How many meanings of the word emum do we need? Whose code does
       | this improve?
        
       ___________________________________________________________________
       (page generated 2024-08-04 23:00 UTC)