Hello C++ friends,A tagged union, in C++ parlance, is a combination of an enum with (different) data attached to each enumerant. Conceptually it's like this pseudo-C++ code:enum class MyEnumOfOptions {KOption1 (int),kOption2 (string),kOption3 (MyStruct),};When using a tagged union, the compiler will ensure that the appropriate data is attached when setting the enum value. For instance when setting it to kOption2, you have to also include the string.This is one of my favourite features of modern programming languages, as it allows you to move all kinds of runtime branches up to compile time, which means you avoid writing bugs. An important part of tagged unions is the matching against them. In C++ we have a switch statement for enums, which allows the language to perform a kind of "matching". But since enums can not hold data, this matching is limited.In the past the effect of tagged union could be emulated by passing around an enum and a union as a pair of parameters, but unions are difficult to hold correctly - especially if they can contain classes. And the compiler provides no safety rails.C++ also has introduced something closer to this ideal which is std::variant. It's like a tagged union, but without the relationship to a union. So matching is normally done on indices, which prevents the compiler from verifying your code at all. It can also be done on types, if every type in your variant is unique, but I find this to be an awkward tool to use in the places where you'd want a tagged union - it means converting an enum into a set of independent structs, losing their relationship to each other in the type system.Mojo does provide a tag on its unions for IPC, though I'm not sure about pulling mojo out for use in non-IPC contexts.Recently this came up in discussion about parameters in WebContentsObserver, where we have avoided passing data that would be useful for handling some enum values because then we present "null data" which can be misused and lead to bugs.So anyhow I thought it might be nice to introduce a TaggedUnion type into C++, built on variant, but marrying it to an actual enum.Do you think this would be useful? I'd love to hear feedback on the idea, the code, and especially if and how you would use this tool if it exists.If there's interest I can work on getting it landed.Thanks,Dana
+chromium-dev from my correct accountOn Fri, Dec 3, 2021 at 11:25 AM Dana Jansens <dan...@google.com> wrote:Hello C++ friends,A tagged union, in C++ parlance, is a combination of an enum with (different) data attached to each enumerant. Conceptually it's like this pseudo-C++ code:enum class MyEnumOfOptions {KOption1 (int),kOption2 (string),kOption3 (MyStruct),};When using a tagged union, the compiler will ensure that the appropriate data is attached when setting the enum value. For instance when setting it to kOption2, you have to also include the string.This is one of my favourite features of modern programming languages, as it allows you to move all kinds of runtime branches up to compile time, which means you avoid writing bugs. An important part of tagged unions is the matching against them. In C++ we have a switch statement for enums, which allows the language to perform a kind of "matching". But since enums can not hold data, this matching is limited.In the past the effect of tagged union could be emulated by passing around an enum and a union as a pair of parameters, but unions are difficult to hold correctly - especially if they can contain classes. And the compiler provides no safety rails.C++ also has introduced something closer to this ideal which is std::variant. It's like a tagged union, but without the relationship to a union.
--
You received this message because you are subscribed to the Google Groups "cxx" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cxx+uns...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CAHtyhaRc6fHEv7ogRoSYmR9sUx%2BYjs-WoXfZtxMPwuqq%3D8ezRQ%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CACuR13eBmj976-p-%2B4VCT4s8ezro%3DJWSKmYEvt28jo%3DiaYjFnQ%40mail.gmail.com.
--
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev
---
You received this message because you are subscribed to the Google Groups "Chromium-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-dev/CACwGi-6x7QR913GGcEz%2BmD6rupzMgDz%3DFpPFRmg2yfe2HJtNNw%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-dev/CAHq1K7RRROZLy5wCcKf7J-6hjSdgottdmbq7QK9HYusXyTBmmA%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CAHtyhaTf1W7HfuX7zoqAUyviFfzBdDSjSAye1EbiwsgNSVMCBg%40mail.gmail.com.
I think it would be interesting to add built-in serialization/deserialization helpers. For example, a deserilaize method that reads the enum value, and then calls the deserialize method on the appropriate data class. This would imply that all data classes implement the same deserialization interface. If that is too restrictive, then perhaps only support POD types.
Also, I wonder whether there would be value in using this pattern in most places in the code where we do some form of ad hoc RTTI (e.g. methods that return some kind of type id that is used to inform downcasting). If I understand this pattern correctly, I think it might make it easier to write code that allocates polymorphic objects on the stack rather than on the heap, which could be beneficial for performance in several places.Another addition to suggest: it would be nice to have a way for a TaggedEnum declaration to specify an interface that all the data classes must implement (or maybe this could be implicit thanks to template magic). Then, TaggedEnum can be a performance primitive that offers a way to do polymorphism without virtual inheritance. This is possible because the TaggedEnum can inline all the override method addresses at compile time since all the data types are part of the declaration.-Justin
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-dev/CAH%3DT95RHmEQxfXS%2BVqrJP4B6nDP17Z2p9cZxL8%2BsKoJShcQYkw%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-dev/CAH%3DT95RHmEQxfXS%2BVqrJP4B6nDP17Z2p9cZxL8%2BsKoJShcQYkw%40mail.gmail.com.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev+unsubscribe@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-dev/CACwGi-6x7QR913GGcEz%2BmD6rupzMgDz%3DFpPFRmg2yfe2HJtNNw%40mail.gmail.com.
--
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev
---
You received this message because you are subscribed to the Google Groups "Chromium-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev+unsubscribe@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-dev/CAHq1K7RRROZLy5wCcKf7J-6hjSdgottdmbq7QK9HYusXyTBmmA%40mail.gmail.com.
--
You received this message because you are subscribed to the Google Groups "cxx" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cxx+uns...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-dev/CABpaAqTq35g%2BvbSF%3DPRZABEOmyp5X%3DQCTtyHtYzrgiiQEUQvrg%40mail.gmail.com.
Nice work. Not sure about actual use cases, but nice to read :-)I played with the code for a while and noticed a couple of things:
- Bikeshedding:
- I would call it TaggedVariant rather than TaggedUnion.
- I found the terms value and data rather confusing and would use tag and type instead.
- It took some time to get used to the factory method being called "With". I would prefer something that indicates the factory aspect, like "Create".
- Not sure if enumeral is an established term? ccpreference.com calls it enumerator, see https://en.cppreference.com/w/cpp/language/enum
- Implementation
- Using fold expressions can shorten the internal code a lot.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-dev/CAHq1K7RRROZLy5wCcKf7J-6hjSdgottdmbq7QK9HYusXyTBmmA%40mail.gmail.com.