Union type
Data type that allows for values that are one of multiple different data types
- 27 min read
- 3 chapters
Related on Lably
Through Computer science, Value (computer science) and Computer memory
A union can be pictured as a chunk of memory that is used to store variables of different data types. Once a new value is assigned to a field, the existing data is overwritten with the new data. The memory area storing the value has no intrinsic type (other than just bytes or words of memory), but the value can be treated as one of several abstract data types, having the type of the value that was last written to the memory area.
In type theory, a union has a sum type; this corresponds to disjoint union in mathematics.
Depending on the language and type, a union value may be used in some operations, such as assignment and comparison for equality, without knowing its specific type. Other operations may require that knowledge, either by some external information, or by the use of a tagged union.
Untagged unions
Because of the limitations of their use, untagged unions are generally only provided in untyped languages or in a type-unsafe way (as in C). They have the advantage over simple tagged unions of not requiring space to store a data type tag.
The name "union" stems from the type's formal definition. If a type is considered as the set of all values that that type can take on, a union type is simply the mathematical union of its constituting types, since it can take on any value any of its fields can. Also, because a mathematical union discards duplicates, if more than one field of the union can take on a single common value, it is impossible to tell from the value alone which field was last written.
However, one useful programming function of unions is to map smaller data elements to larger ones for easier manipulation. A data structure consisting, for example, of 4 bytes and a 32-bit integer, can form a union with an unsigned 64-bit integer, and thus be more readily accessed for purposes of comparison etc.
Sign in to keep reading
2 more chapters are free with a Lably account.
Unions in various programming languages
ALGOL 68
ALGOL 68 has tagged unions, and uses a case clause to distinguish and extract the constituent type at runtime. A union containing another union is treated as the set of all its constituent possibilities, and if the context requires it a union is automatically coerced into the wider union. A union can explicitly contain no value, which can be distinguished at runtime. An example is:
<b id="mwLA">mode</b> <b id="mwLQ">node</b> = <b id="mwLg">union</b> (<b id="mwLw">real</b>, <b id="mwMA">int</b>, <b id="mwMQ">string</b>, <b id="mwMg">void</b>); <b id="mwMw">node</b> n := "abc"; <b id="mwNA">case</b> n <b id="mwNQ">in</b> (<b id="mwNg">real</b> r): print(("real:", r)), (<b id="mwNw">int</b> i): print(("int:", i)), (<b id="mwOA">string</b> s): print(("string:", s)), (<b id="mwOQ">void</b>): print(("void:", "EMPTY")), <b id="mwOg">out</b> print(("?:", n)) <b id="mwOw">esac</b>The syntax of the C/C++ union type and the notion of casts was derived from ALGOL 68, though in an untagged form.
C/C++
In C and C++, untagged unions are expressed nearly exactly like structures (structs), except that each data member is located at the same memory address. The data members, as in structures, need not be primitive values, and in fact may be structures or even other unions. C++ (since C++11) also allows for a data member to be any type that has a full-fledged constructor/destructor and/or copy constructor, or a non-trivial copy assignment operator. For example, it is possible to have the standard C++ string as a member of a union.
The primary use of a union is allowing access to a common location by different data types, for example hardware input/output access, bitfield and word sharing, or type punning. Unions can also provide low-level polymorphism. However, there is no checking of types, so it is up to the programmer to be sure that the proper fields are accessed in different contexts. The relevant field of a union variable is typically determined by the state of other variables, possibly in an enclosing struct.
One common C programming idiom uses unions to perform what C++ calls a reinterpret_cast, by assigning to one field of a union and reading from another, as is done in code which depends on the raw representation of the values. A practical example is the method of computing square roots using the IEEE representation. This is not, however, a safe use of unions in general.
Structure and union specifiers have the same form. [ . . . ] The size of a union is sufficient to contain the largest of its members. The value of at most one of the members can be stored in a union object at any time. A pointer to a union object, suitably converted, points to each of its members (or if a member is a bit-field, then to the unit in which it resides), and vice versa.
— ANSI/ISO 9899:1990 (the ANSI C standard) Section 6.5.2.1
Anonymous union
In C++, C11, and as a non-standard extension in many compilers, unions can also be anonymous. Their data members do not need to be referenced, are instead accessed directly. They have some restrictions as opposed to traditional unions: in C11, they must be a member of another structure or union, and in C++, they can not have methods or access specifiers.
Simply omitting the class-name portion of the syntax does not make a union an anonymous union. For a union to qualify as an anonymous union, the declaration must not declare an object. Example:
<span id="mwXA"></span><span class="k" id="mwXQ">union</span><span class="w" id="mwXg"> </span><span class="p" id="mwXw">{</span> <span class="w" id="mwYA"> </span><span class="kt" id="mwYQ">float</span><span class="w" id="mwYg"> </span><span class="n" id="mwYw">f</span><span class="p" id="mwZA">;</span> <span class="w" id="mwZQ"> </span><span class="kt" id="mwZg">uint32_t</span><span class="w" id="mwZw"> </span><span class="n" id="mwaA">d</span><span class="p" id="mwaQ">;</span><span class="w" id="mwag"> </span><span class="c1" id="mwaw">// Assumes float is 32 bits wide</span> <span class="p" id="mwbA">};</span> <span class="n" id="mwbQ">f</span><span class="w" id="mwbg"> </span><span class="o" id="mwbw">=</span><span class="w" id="mwcA"> </span><span class="mf" id="mwcQ">3.14f</span><span class="p" id="mwcg">;</span> <span class="n" id="mwcw">printf</span><span class="p" id="mwdA">(</span><span class="s" id="mwdQ">"Hexadecimal representation of 3.14f: %x</span><span class="se" id="mwdg">\n</span><span class="s" id="mwdw">"</span><span class="p" id="mweA">,</span><span class="w" id="mweQ"> </span><span class="n" id="mweg">d</span><span class="p" id="mwew">);</span>Anonymous unions are also useful in C struct definitions to provide a sense of namespacing.
Transparent union
In compilers such as GCC, Clang, and IBM XL C for AIX, a transparent_union attribute is available for union types. Types contained in the union can be converted transparently to the union type itself in a function call, provided that all types have the same size. It is mainly intended for function with multiple parameter interfaces, a use necessitated by early Unix extensions and later re-standardisation.
COBOL
In COBOL, union data items are defined in two ways. The first uses the RENAMES (66 level) keyword, which effectively maps a second alphanumeric data item on top of the same memory location as a preceding data item. In the example code below, data item PERSON-REC is defined as a group containing another group and a numeric data item. PERSON-DATA is defined as an alphanumeric data item that renames PERSON-REC, treating the data bytes continued within it as character data.
<span id="mwlg"></span><span class="c" id="mwlw"> 01 </span><span class="nv" id="mwmA">PERSON-REC</span><span class="p" id="mwmQ">.</span> <span class="c" id="mwmg"> </span><span class="mi" id="mwmw">05 </span><span class="nv" id="mwnA">PERSON-NAME</span><span class="p" id="mwnQ">.</span> <span class="c" id="mwng"> </span><span class="w" id="mwnw"> </span><span class="mi" id="mwoA">10 </span><span class="nv" id="mwoQ">PERSON-NAME-LAST</span><span class="w" id="mwog"> </span><span class="kt" id="mwow">PIC X(12)</span><span class="p" id="mwpA">.</span> <span class="c" id="mwpQ"> </span><span class="w" id="mwpg"> </span><span class="mi" id="mwpw">10 </span><span class="nv" id="mwqA">PERSON-NAME-FIRST</span><span class="w" id="mwqQ"> </span><span class="kt" id="mwqg">PIC X(16)</span><span class="p" id="mwqw">.</span> <span class="c" id="mwrA"> </span><span class="w" id="mwrQ"> </span><span class="mi" id="mwrg">10 </span><span class="nv" id="mwrw">PERSON-NAME-MID</span><span class="w" id="mwsA"> </span><span class="kt" id="mwsQ">PIC X</span><span class="p" id="mwsg">.</span> <span class="c" id="mwsw"> </span><span class="mi" id="mwtA">05 </span><span class="nv" id="mwtQ">PERSON-ID</span><span class="w" id="mwtg"> </span><span class="kt" id="mwtw">PIC 9(9)</span><span class="w" id="mwuA"> </span><span class="kp" id="mwuQ">PACKED-DECIMAL</span><span class="p" id="mwug">.</span> <span class="w" id="mwuw"> </span> <span class="c" id="mwvA"> 01 </span><span class="nv" id="mwvQ">PERSON-DATA</span><span class="w" id="mwvg"> </span><span class="kp" id="mwvw">RENAMES</span><span class="w" id="mwwA"> </span><span class="nv" id="mwwQ">PERSON-REC</span><span class="p" id="mwwg">.</span>
The second way to define a union type is by using the REDEFINES keyword. In the example code below, data item VERS-NUM is defined as a 2-byte binary integer containing a version number. A second data item VERS-BYTES is defined as a two-character alphanumeric variable. Since the second item is redefined over the first item, the two items share the same address in memory, and therefore share the same underlying data bytes. The first item interprets the two data bytes as a binary value, while the second item interprets the bytes as character values.
<span id="mwzQ"></span><span class="c" id="mwzg"> 01 </span><span class="nv" id="mwzw">VERS-INFO</span><span class="p" id="mw0A">.</span> <span class="c" id="mw0Q"> </span><span class="mi" id="mw0g">05 </span><span class="nv" id="mw0w">VERS-NUM</span><span class="w" id="mw1A"> </span><span class="kt" id="mw1Q">PIC S9(4)</span><span class="w" id="mw1g"> </span><span class="kt" id="mw1w">COMP</span><span class="p" id="mw2A">.</span> <span class="c" id="mw2Q"> </span><span class="mi" id="mw2g">05 </span><span class="nv" id="mw2w">VERS-BYTES</span><span class="w" id="mw3A"> </span><span class="kt" id="mw3Q">PIC X(2)</span> <span class="kt" id="mw3g"> </span><span class="w" id="mw3w"> </span><span class="kp" id="mw4A">REDEFINES</span><span class="w" id="mw4Q"> </span><span class="nv" id="mw4g">VERS-NUM</span>
Pascal
In Pascal, there are two ways to create unions. One is the standard way through a variant record. The second is a nonstandard means of declaring a variable as absolute, meaning it is placed at the same memory location as another variable or at an absolute address. While all Pascal compilers support variant records, only some support absolute variables.
For the purposes of this example, the following are all integer types: a byte consists of 8 bits, a word is 16 bits, and an integer is 32 bits.
The following example shows the non-standard absolute form:
<span id="mw7Q"></span><span class="k" id="mw7g">var</span> <span class="w" id="mw7w"> </span><span class="n" id="mw8A">A</span><span class="o" id="mw8Q">:</span><span class="w" id="mw8g"> </span><span class="kt" id="mw8w">Integer</span><span class="o" id="mw9A">;</span> <span class="w" id="mw9Q"> </span><span class="n" id="mw9g">B</span><span class="o" id="mw9w">:</span><span class="w" id="mw-A"> </span><span class="k" id="mw-Q">array</span><span class="p" id="mw-g">[</span><span class="mi" id="mw-w">1</span><span class="o" id="mw_A">..</span><span class="mi" id="mw_Q">4</span><span class="p" id="mw_g">]</span><span class="w" id="mw_w"> </span><span class="k" id="mwAQA">of</span><span class="w" id="mwAQE"> </span><span class="kt" id="mwAQI">Byte</span><span class="w" id="mwAQM"> </span><span class="k" id="mwAQQ">absolute</span><span class="w" id="mwAQU"> </span><span class="n" id="mwAQY">A</span><span class="o" id="mwAQc">;</span> <span class="w" id="mwAQg"> </span><span class="n" id="mwAQk">C</span><span class="o" id="mwAQo">:</span><span class="w" id="mwAQs"> </span><span class="kt" id="mwAQw">Integer</span><span class="w" id="mwAQ0"> </span><span class="k" id="mwAQ4">absolute</span><span class="w" id="mwAQ8"> </span><span class="mi" id="mwARA">0</span><span class="o" id="mwARE">;</span>
In the first example, each of the elements of the array B maps to one of the specific bytes of the variable A. In the second example, the variable C is assigned to the exact machine address 0.
In the following example, a record has variants, some of which share the same location as others:
<span id="mwARY"></span><span class="k" id="mwARc">type</span> <span class="w" id="mwARg"> </span><span class="n" id="mwARk">Shape</span><span class="w" id="mwARo"> </span><span class="o" id="mwARs">=</span><span class="w" id="mwARw"> </span><span class="p" id="mwAR0">(</span><span class="n" id="mwAR4">Circle</span><span class="o" id="mwAR8">,</span><span class="w" id="mwASA"> </span><span class="n" id="mwASE">Square</span><span class="o" id="mwASI">,</span><span class="w" id="mwASM"> </span><span class="n" id="mwASQ">Triangle</span><span class="p" id="mwASU">)</span><span class="o" id="mwASY">;</span> <span class="w" id="mwASc"> </span><span class="n" id="mwASg">Dimensions</span><span class="w" id="mwASk"> </span><span class="o" id="mwASo">=</span><span class="w" id="mwASs"> </span><span class="k" id="mwASw">record</span> <span class="w" id="mwAS0"> </span><span class="k" id="mwAS4">case</span><span class="w" id="mwAS8"> </span><span class="n" id="mwATA">Figure</span><span class="o" id="mwATE">:</span><span class="w" id="mwATI"> </span><span class="n" id="mwATM">Shape</span><span class="w" id="mwATQ"> </span><span class="k" id="mwATU">of</span><span class="w" id="mwATY"> </span> <span class="w" id="mwATc"> </span><span class="n" id="mwATg">Circle</span><span class="o" id="mwATk">:</span><span class="w" id="mwATo"> </span><span class="p" id="mwATs">(</span><span class="n" id="mwATw">Diameter</span><span class="o" id="mwAT0">:</span><span class="w" id="mwAT4"> </span><span class="kt" id="mwAT8">real</span><span class="p" id="mwAUA">)</span><span class="o" id="mwAUE">;</span> <span class="w" id="mwAUI"> </span><span class="n" id="mwAUM">Square</span><span class="o" id="mwAUQ">:</span><span class="w" id="mwAUU"> </span><span class="p" id="mwAUY">(</span><span class="n" id="mwAUc">Width</span><span class="o" id="mwAUg">:</span><span class="w" id="mwAUk"> </span><span class="kt" id="mwAUo">real</span><span class="p" id="mwAUs">)</span><span class="o" id="mwAUw">;</span> <span class="w" id="mwAU0"> </span><span class="n" id="mwAU4">Triangle</span><span class="o" id="mwAU8">:</span><span class="w" id="mwAVA"> </span><span class="p" id="mwAVE">(</span><span class="n" id="mwAVI">Side</span><span class="o" id="mwAVM">:</span><span class="w" id="mwAVQ"> </span><span class="kt" id="mwAVU">real</span><span class="o" id="mwAVY">;</span><span class="w" id="mwAVc"> </span><span class="n" id="mwAVg">Angle1</span><span class="o" id="mwAVk">,</span><span class="w" id="mwAVo"> </span><span class="n" id="mwAVs">Angle2</span><span class="o" id="mwAVw">:</span><span class="w" id="mwAV0"> </span><span class="mi" id="mwAV4">0</span><span class="o" id="mwAV8">..</span><span class="mi" id="mwAWA">360</span><span class="p" id="mwAWE">)</span> <span class="w" id="mwAWI"> </span><span class="k" id="mwAWM">end</span><span class="o" id="mwAWQ">;</span>
PL/I
In PL/I the original term for a union was cell, which is still accepted as a synonym for union by several compilers. The union declaration is similar to the structure definition, where elements at the same level within the union declaration occupy the same storage. Elements of the union can be any data type, including structures and array. Here vers_num and vers_bytes occupy the same storage locations.
<span id="mwAXQ"></span><span class="w" id="mwAXU"> </span><span class="mi" id="mwAXY">1 </span><span class="nv" id="mwAXc">vers_info</span><span class="w" id="mwAXg"> </span><span class="nv" id="mwAXk">union</span><span class="p" id="mwAXo">,</span> <span class="w" id="mwAXs"> </span><span class="mi" id="mwAXw">5 </span><span class="nv" id="mwAX0">vers_num</span><span class="w" id="mwAX4"> </span><span class="kp" id="mwAX8">fixed</span><span class="w" id="mwAYA"> </span><span class="kt" id="mwAYE">binary</span><span class="p" id="mwAYI">,</span> <span class="w" id="mwAYM"> </span><span class="mi" id="mwAYQ">5 </span><span class="nv" id="mwAYU">vers_bytes</span><span class="w" id="mwAYY"> </span><span class="kt" id="mwAYc">pic '(2)A';</span>
An alternative to a union declaration is the DEFINED attribute, which allows alternative declarations of storage, however the data types of the base and defined variables must match.
Rust
Rust implements both tagged and untagged unions. In Rust, tagged unions are implemented using the enum keyword. Unlike enumerated types in most other languages, enum variants in Rust can contain additional data in the form of a tuple or struct, making them tagged unions rather than simple enumerated types.
Rust also supports untagged unions using the union keyword. The memory layout of unions in Rust is undefined by default, but a union with the #[repr(C)] attribute will be laid out in memory exactly like the equivalent union in C. Reading the fields of a union can only be done within an unsafe function or block, as the compiler cannot guarantee that the data in the union will be valid for the type of the field; if this is not the case, it will result in undefined behavior.
Syntax and example
C
In C, a simplified version of the syntax is:
<span id="mwAbE"></span><span class="k" id="mwAbI">union</span><span class="w" id="mwAbM"> </span><span class="o" id="mwAbQ"><</span><span class="n" id="mwAbU">name</span><span class="o" id="mwAbY">></span><span class="w" id="mwAbc"> </span><span class="p" id="mwAbg">{</span> <span class="w" id="mwAbk"> </span><span class="o" id="mwAbo"><</span><span class="n" id="mwAbs">datatype</span><span class="o" id="mwAbw">></span><span class="w" id="mwAb0"> </span><span class="o" id="mwAb4"><</span><span class="mi" id="mwAb8">1</span><span class="n" id="mwAcA">st</span><span class="w" id="mwAcE"> </span><span class="n" id="mwAcI">variable</span><span class="w" id="mwAcM"> </span><span class="n" id="mwAcQ">name</span><span class="o" id="mwAcU">></span><span class="p" id="mwAcY">;</span> <span class="w" id="mwAcc"> </span><span class="o" id="mwAcg"><</span><span class="n" id="mwAck">datatype</span><span class="o" id="mwAco">></span><span class="w" id="mwAcs"> </span><span class="o" id="mwAcw"><</span><span class="mi" id="mwAc0">2</span><span class="n" id="mwAc4">nd</span><span class="w" id="mwAc8"> </span><span class="n" id="mwAdA">variable</span><span class="w" id="mwAdE"> </span><span class="n" id="mwAdI">name</span><span class="o" id="mwAdM">></span><span class="p" id="mwAdQ">;</span> <span class="w" id="mwAdU"> </span><span class="p" id="mwAdY">.</span> <span class="w" id="mwAdc"> </span><span class="p" id="mwAdg">.</span> <span class="w" id="mwAdk"> </span><span class="p" id="mwAdo">.</span> <span class="w" id="mwAds"> </span><span class="o" id="mwAdw"><</span><span class="n" id="mwAd0">datatype</span><span class="o" id="mwAd4">></span><span class="w" id="mwAd8"> </span><span class="o" id="mwAeA"><</span><span class="n" id="mwAeE">nth</span><span class="w" id="mwAeI"> </span><span class="n" id="mwAeM">variable</span><span class="w" id="mwAeQ"> </span><span class="n" id="mwAeU">name</span><span class="o" id="mwAeY">></span><span class="p" id="mwAec">;</span> <span class="p" id="mwAeg">}</span><span class="w" id="mwAek"> </span><span class="o" id="mwAeo"><</span><span class="k" id="mwAes">union</span><span class="w" id="mwAew"> </span><span class="nc" id="mwAe0">variable</span><span class="w" id="mwAe4"> </span><span class="n" id="mwAe8">name</span><span class="o" id="mwAfA">></span><span class="p" id="mwAfE">;</span>A structure can also be a member of a union, as the following example shows:
<span id="mwAfU"></span><span class="k" id="mwAfY">union</span><span class="w" id="mwAfc"> </span><span class="p" id="mwAfg">{</span> <span class="w" id="mwAfk"> </span><span class="k" id="mwAfo">struct</span><span class="w" id="mwAfs"> </span><span class="p" id="mwAfw">{</span><span class="w" id="mwAf0"> </span> <span class="w" id="mwAf4"> </span><span class="kt" id="mwAf8">int</span><span class="w" id="mwAgA"> </span><span class="n" id="mwAgE">a</span><span class="p" id="mwAgI">;</span> <span class="w" id="mwAgM"> </span><span class="kt" id="mwAgQ">float</span><span class="w" id="mwAgU"> </span><span class="n" id="mwAgY">b</span><span class="p" id="mwAgc">;</span> <span class="w" id="mwAgg"> </span><span class="kt" id="mwAgk">char</span><span class="w" id="mwAgo"> </span><span class="n" id="mwAgs">c</span><span class="p" id="mwAgw">;</span> <span class="w" id="mwAg0"> </span><span class="p" id="mwAg4">}</span><span class="w" id="mwAg8"> </span><span class="n" id="mwAhA">svar</span><span class="p" id="mwAhE">;</span> <span class="w" id="mwAhI"> </span><span class="kt" id="mwAhM">int</span><span class="w" id="mwAhQ"> </span><span class="n" id="mwAhU">d</span><span class="p" id="mwAhY">;</span> <span class="p" id="mwAhc">}</span><span class="w" id="mwAhg"> </span><span class="n" id="mwAhk">uvar</span><span class="p" id="mwAho">;</span>This example defines a variable uvar as a union which contains two members, a structure named svar (which in turn contains three members), and an integer variable named d.
Unions may occur within structures and arrays, and vice versa:
<span id="mwAiI"></span><span class="cp" id="mwAiM">#define N 10000</span> <span class="k" id="mwAiQ">struct</span><span class="w" id="mwAiU"> </span><span class="p" id="mwAiY">{</span><span class="w" id="mwAic"> </span> <span class="w" id="mwAig"> </span><span class="kt" id="mwAik">int</span><span class="w" id="mwAio"> </span><span class="n" id="mwAis">flags</span><span class="p" id="mwAiw">;</span> <span class="w" id="mwAi0"> </span><span class="kt" id="mwAi4">char</span><span class="w" id="mwAi8"> </span><span class="o" id="mwAjA">*</span><span class="n" id="mwAjE">name</span><span class="p" id="mwAjI">;</span> <span class="w" id="mwAjM"> </span><span class="kt" id="mwAjQ">int</span><span class="w" id="mwAjU"> </span><span class="n" id="mwAjY">utype</span><span class="p" id="mwAjc">;</span> <span class="w" id="mwAjg"> </span><span class="k" id="mwAjk">union</span><span class="w" id="mwAjo"> </span><span class="p" id="mwAjs">{</span> <span class="w" id="mwAjw"> </span><span class="kt" id="mwAj0">int</span><span class="w" id="mwAj4"> </span><span class="n" id="mwAj8">ival</span><span class="p" id="mwAkA">;</span> <span class="w" id="mwAkE"> </span><span class="kt" id="mwAkI">float</span><span class="w" id="mwAkM"> </span><span class="n" id="mwAkQ">fval</span><span class="p" id="mwAkU">;</span> <span class="w" id="mwAkY"> </span><span class="kt" id="mwAkc">char</span><span class="w" id="mwAkg"> </span><span class="o" id="mwAkk">*</span><span class="n" id="mwAko">sval</span><span class="p" id="mwAks">;</span> <span class="w" id="mwAkw"> </span><span class="p" id="mwAk0">}</span><span class="w" id="mwAk4"> </span><span class="n" id="mwAk8">u</span><span class="p" id="mwAlA">;</span> <span class="p" id="mwAlE">}</span><span class="w" id="mwAlI"> </span><span class="n" id="mwAlM">symtab</span><span class="p" id="mwAlQ">[</span><span class="n" id="mwAlU">N</span><span class="p" id="mwAlY">];</span>The number ival is referred to by symtab[i].u.ival and the string sval by symtab[i].u.sval.
C++
C++ supports unions like C, but they are difficult to use safely in C++. For the two main purposes of unions, idiomatic C++ has alternatives:
- Type punning via unions like
union { uint32_t x; float y; }to map from a floating-point value to its binary representation as an integer can be done withstd::bit_cast.reinterpret_castcannot be used for this in most cases due to the strict aliasing rule.
- For non-POD types, unions require explicit construction and destruction, making them cumbersome to use safely.
std::variant, introduced in C++17, acts as a tagged union, avoiding this complication.
<span id="mwAok"></span><span class="cp" id="mwAoo">#include</span><span class="w" id="mwAos"> </span><span class="cpf" id="mwAow"><bit></span> <span class="cp" id="mwAo0">#include</span><span class="w" id="mwAo4"> </span><span class="cpf" id="mwAo8"><cmath></span> <span class="cp" id="mwApA">#include</span><span class="w" id="mwApE"> </span><span class="cpf" id="mwApI"><cstdint></span> <span class="cp" id="mwApM">#include</span><span class="w" id="mwApQ"> </span><span class="cpf" id="mwApU"><stdexcept></span> <span class="cp" id="mwApY">#include</span><span class="w" id="mwApc"> </span><span class="cpf" id="mwApg"><variant></span> <span class="kt" id="mwApk">uint32_t</span><span class="w" id="mwApo"> </span><span class="nf" id="mwAps">encode_float_as_binary</span><span class="p" id="mwApw">(</span><span class="kt" id="mwAp0">float</span><span class="w" id="mwAp4"> </span><span class="n" id="mwAp8">f</span><span class="p" id="mwAqA">)</span><span class="w" id="mwAqE"> </span><span class="k" id="mwAqI">noexcept</span><span class="w" id="mwAqM"> </span><span class="p" id="mwAqQ">{</span> <span class="w" id="mwAqU"> </span><span class="c1" id="mwAqY">// return reinterpret_cast<uint32_t&>(f); // UB</span> <span class="w" id="mwAqc"> </span><span class="k" id="mwAqg">return</span><span class="w" id="mwAqk"> </span><span class="n" id="mwAqo">std</span><span class="o" id="mwAqs">::</span><span class="n" id="mwAqw">bit_cast</span><span class="o" id="mwAq0"><</span><span class="kt" id="mwAq4">uint32_t</span><span class="o" id="mwAq8">></span><span class="p" id="mwArA">(</span><span class="n" id="mwArE">f</span><span class="p" id="mwArI">);</span> <span class="p" id="mwArM">}</span> <span class="kt" id="mwArQ">bool</span><span class="w" id="mwArU"> </span><span class="nf" id="mwArY">is_integral</span><span class="p" id="mwArc">(</span><span class="n" id="mwArg">std</span><span class="o" id="mwArk">::</span><span class="n" id="mwAro">variant</span><span class="o" id="mwArs"><</span><span class="kt" id="mwArw">int</span><span class="p" id="mwAr0">,</span><span class="w" id="mwAr4"> </span><span class="kt" id="mwAr8">float</span><span class="o" id="mwAsA">>&</span><span class="w" id="mwAsE"> </span><span class="n" id="mwAsI">v</span><span class="p" id="mwAsM">)</span><span class="w" id="mwAsQ"> </span><span class="p" id="mwAsU">{</span> <span class="w" id="mwAsY"> </span><span class="k" id="mwAsc">if</span><span class="w" id="mwAsg"> </span><span class="p" id="mwAsk">(</span><span class="kt" id="mwAso">int</span><span class="o" id="mwAss">*</span><span class="w" id="mwAsw"> </span><span class="n" id="mwAs0">_</span><span class="w" id="mwAs4"> </span><span class="o" id="mwAs8">=</span><span class="w" id="mwAtA"> </span><span class="n" id="mwAtE">std</span><span class="o" id="mwAtI">::</span><span class="n" id="mwAtM">get_if</span><span class="o" id="mwAtQ"><</span><span class="kt" id="mwAtU">int</span><span class="o" id="mwAtY">></span><span class="p" id="mwAtc">(</span><span class="o" id="mwAtg">&</span><span class="n" id="mwAtk">v</span><span class="p" id="mwAto">))</span><span class="w" id="mwAts"> </span><span class="p" id="mwAtw">{</span> <span class="w" id="mwAt0"> </span><span class="k" id="mwAt4">return</span><span class="w" id="mwAt8"> </span><span class="nb" id="mwAuA">true</span><span class="p" id="mwAuE">;</span> <span class="w" id="mwAuI"> </span><span class="p" id="mwAuM">}</span><span class="w" id="mwAuQ"> </span><span class="k" id="mwAuU">else</span><span class="w" id="mwAuY"> </span><span class="k" id="mwAuc">if</span><span class="w" id="mwAug"> </span><span class="p" id="mwAuk">(</span><span class="kt" id="mwAuo">float</span><span class="o" id="mwAus">*</span><span class="w" id="mwAuw"> </span><span class="n" id="mwAu0">f</span><span class="w" id="mwAu4"> </span><span class="o" id="mwAu8">=</span><span class="w" id="mwAvA"> </span><span class="n" id="mwAvE">std</span><span class="o" id="mwAvI">::</span><span class="n" id="mwAvM">get_if</span><span class="o" id="mwAvQ"><</span><span class="kt" id="mwAvU">float</span><span class="o" id="mwAvY">></span><span class="p" id="mwAvc">(</span><span class="o" id="mwAvg">&</span><span class="n" id="mwAvk">v</span><span class="p" id="mwAvo">))</span><span class="w" id="mwAvs"> </span><span class="p" id="mwAvw">{</span> <span class="w" id="mwAv0"> </span><span class="k" id="mwAv4">return</span><span class="w" id="mwAv8"> </span><span class="n" id="mwAwA">std</span><span class="o" id="mwAwE">::</span><span class="n" id="mwAwI">modff</span><span class="p" id="mwAwM">(</span><span class="o" id="mwAwQ">*</span><span class="n" id="mwAwU">f</span><span class="p" id="mwAwY">,</span><span class="w" id="mwAwc"> </span><span class="nb" id="mwAwg">nullptr</span><span class="p" id="mwAwk">)</span><span class="w" id="mwAwo"> </span><span class="o" id="mwAws">==</span><span class="w" id="mwAww"> </span><span class="mi" id="mwAw0">0</span><span class="p" id="mwAw4">;</span> <span class="w" id="mwAw8"> </span><span class="p" id="mwAxA">}</span> <span class="w" id="mwAxE"> </span><span class="k" id="mwAxI">throw</span><span class="w" id="mwAxM"> </span><span class="n" id="mwAxQ">std</span><span class="o" id="mwAxU">::</span><span class="n" id="mwAxY">invalid_argument</span><span class="p" id="mwAxc">(</span><span class="s" id="mwAxg">"Invalid variant input!"</span><span class="p" id="mwAxk">);</span> <span class="p" id="mwAxo">}</span>C#
Until C# 15, there were no union types in C#. The closest way to emulate them was through records and pattern matching.
<span id="mwAyA"></span><span class="k" id="mwAyE">namespace</span><span class="w" id="mwAyI"> </span><span class="nn" id="mwAyM">Wikipedia.Examples</span><span class="p" id="mwAyQ">;</span> <span class="k" id="mwAyU">using</span><span class="w" id="mwAyY"> </span><span class="nn" id="mwAyc">System</span><span class="p" id="mwAyg">;</span> <span class="k" id="mwAyk">abstract</span><span class="w" id="mwAyo"> </span><span class="k" id="mwAys">record</span><span class="w" id="mwAyw"> </span><span class="n" id="mwAy0">Shape</span><span class="p" id="mwAy4">;</span> <span class="k" id="mwAy8">record</span><span class="w" id="mwAzA"> </span><span class="nf" id="mwAzE">Circle</span><span class="p" id="mwAzI">(</span><span class="kt" id="mwAzM">double</span><span class="w" id="mwAzQ"> </span><span class="n" id="mwAzU">Radius</span><span class="p" id="mwAzY">)</span><span class="w" id="mwAzc"> </span><span class="p" id="mwAzg">:</span><span class="w" id="mwAzk"> </span><span class="n" id="mwAzo">Shape</span><span class="p" id="mwAzs">;</span> <span class="k" id="mwAzw">record</span><span class="w" id="mwAz0"> </span><span class="nf" id="mwAz4">Rectangle</span><span class="p" id="mwAz8">(</span><span class="kt" id="mwA0A">double</span><span class="w" id="mwA0E"> </span><span class="n" id="mwA0I">Width</span><span class="p" id="mwA0M">,</span><span class="w" id="mwA0Q"> </span><span class="kt" id="mwA0U">double</span><span class="w" id="mwA0Y"> </span><span class="n" id="mwA0c">Height</span><span class="p" id="mwA0g">)</span><span class="w" id="mwA0k"> </span><span class="p" id="mwA0o">:</span><span class="w" id="mwA0s"> </span><span class="n" id="mwA0w">Shape</span><span class="p" id="mwA00">;</span> <span class="k" id="mwA04">public</span><span class="w" id="mwA08"> </span><span class="k" id="mwA1A">class</span><span class="w" id="mwA1E"> </span><span class="nc" id="mwA1I">Example</span> <span class="p" id="mwA1M">{</span> <span class="w" id="mwA1Q"> </span><span class="k" id="mwA1U">public</span><span class="w" id="mwA1Y"> </span><span class="k" id="mwA1c">static</span><span class="w" id="mwA1g"> </span><span class="kt" id="mwA1k">double</span><span class="w" id="mwA1o"> </span><span class="nf" id="mwA1s">Area</span><span class="p" id="mwA1w">(</span><span class="n" id="mwA10">Shape</span><span class="w" id="mwA14"> </span><span class="n" id="mwA18">s</span><span class="p" id="mwA2A">)</span><span class="w" id="mwA2E"> </span><span class="o" id="mwA2I">=></span><span class="w" id="mwA2M"> </span><span class="n" id="mwA2Q">s</span><span class="w" id="mwA2U"> </span><span class="k" id="mwA2Y">switch</span> <span class="w" id="mwA2c"> </span><span class="p" id="mwA2g">{</span> <span class="w" id="mwA2k"> </span><span class="n" id="mwA2o">Circle</span><span class="w" id="mwA2s"> </span><span class="n" id="mwA2w">c</span><span class="w" id="mwA20"> </span><span class="o" id="mwA24">=></span><span class="w" id="mwA28"> </span><span class="n" id="mwA3A">Math</span><span class="p" id="mwA3E">.</span><span class="n" id="mwA3I">PI</span><span class="w" id="mwA3M"> </span><span class="o" id="mwA3Q">*</span><span class="w" id="mwA3U"> </span><span class="n" id="mwA3Y">c</span><span class="p" id="mwA3c">.</span><span class="n" id="mwA3g">Radius</span><span class="w" id="mwA3k"> </span><span class="o" id="mwA3o">*</span><span class="w" id="mwA3s"> </span><span class="n" id="mwA3w">c</span><span class="p" id="mwA30">.</span><span class="n" id="mwA34">Radius</span><span class="p" id="mwA38">,</span> <span class="w" id="mwA4A"> </span><span class="n" id="mwA4E">Rectangle</span><span class="w" id="mwA4I"> </span><span class="n" id="mwA4M">r</span><span class="w" id="mwA4Q"> </span><span class="o" id="mwA4U">=></span><span class="w" id="mwA4Y"> </span><span class="n" id="mwA4c">r</span><span class="p" id="mwA4g">.</span><span class="n" id="mwA4k">Width</span><span class="w" id="mwA4o"> </span><span class="o" id="mwA4s">*</span><span class="w" id="mwA4w"> </span><span class="n" id="mwA40">r</span><span class="p" id="mwA44">.</span><span class="n" id="mwA48">Height</span><span class="p" id="mwA5A">,</span> <span class="w" id="mwA5E"> </span><span class="n" id="mwA5I">_</span><span class="w" id="mwA5M"> </span><span class="o" id="mwA5Q">=></span><span class="w" id="mwA5U"> </span><span class="k" id="mwA5Y">throw</span><span class="w" id="mwA5c"> </span><span class="k" id="mwA5g">new</span><span class="w" id="mwA5k"> </span><span class="n" id="mwA5o">NotSupportedException</span><span class="p" id="mwA5s">()</span> <span class="w" id="mwA5w"> </span><span class="p" id="mwA50">};</span> <span class="p" id="mwA54">}</span>They could also be closely simulated using low-level layout. The following demonstrates such a union, where the fields occupy the same memory, but is not type-safe. It is best used for interoperability, serialization, and unsafe manipulation.
<span id="mwA6I"></span><span class="k" id="mwA6M">using</span><span class="w" id="mwA6Q"> </span><span class="nn" id="mwA6U">System.Runtime.InteropServices</span><span class="p" id="mwA6Y">;</span> <span class="c1" id="mwA6c">// closest to C union IntFloatUnion { int i; float f; };</span> <span class="na" id="mwA6g">[StructLayout(LayoutKind.Explicit)]</span> <span class="k" id="mwA6k">struct</span><span class="w" id="mwA6o"> </span><span class="nc" id="mwA6s">IntFloatUnion</span> <span class="p" id="mwA6w">{</span> <span class="w" id="mwA60"> </span><span class="na" id="mwA64">[FieldOffset(0)]</span> <span class="w" id="mwA68"> </span><span class="k" id="mwA7A">public</span><span class="w" id="mwA7E"> </span><span class="kt" id="mwA7I">int</span><span class="w" id="mwA7M"> </span><span class="n" id="mwA7Q">IntValue</span><span class="p" id="mwA7U">;</span> <span class="w" id="mwA7Y"> </span><span class="na" id="mwA7c">[FieldOffset(0)]</span> <span class="w" id="mwA7g"> </span><span class="k" id="mwA7k">public</span><span class="w" id="mwA7o"> </span><span class="kt" id="mwA7s">float</span><span class="w" id="mwA7w"> </span><span class="n" id="mwA70">FloatValue</span><span class="p" id="mwA74">;</span> <span class="p" id="mwA78">}</span>In C# 15, unions were introduced to the language, as can be demonstrated by the following:
<span id="mwA8c"></span><span class="k" id="mwA8g">public</span><span class="w" id="mwA8k"> </span><span class="k" id="mwA8o">record</span><span class="w" id="mwA8s"> </span><span class="k" id="mwA8w">class</span><span class="w" id="mwA80"> </span><span class="nf" id="mwA84">Car</span><span class="p" id="mwA88">(</span><span class="kt" id="mwA9A">string</span><span class="w" id="mwA9E"> </span><span class="n" id="mwA9I">Model</span><span class="p" id="mwA9M">);</span> <span class="k" id="mwA9Q">public</span><span class="w" id="mwA9U"> </span><span class="k" id="mwA9Y">record</span><span class="w" id="mwA9c"> </span><span class="k" id="mwA9g">class</span><span class="w" id="mwA9k"> </span><span class="nf" id="mwA9o">Bicycle</span><span class="p" id="mwA9s">(</span><span class="kt" id="mwA9w">string</span><span class="w" id="mwA90"> </span><span class="n" id="mwA94">Model</span><span class="p" id="mwA98">);</span> <span class="k" id="mwA-A">public</span><span class="w" id="mwA-E"> </span><span class="k" id="mwA-I">record</span><span class="w" id="mwA-M"> </span><span class="k" id="mwA-Q">class</span><span class="w" id="mwA-U"> </span><span class="nf" id="mwA-Y">Bus</span><span class="p" id="mwA-c">(</span><span class="kt" id="mwA-g">string</span><span class="w" id="mwA-k"> </span><span class="n" id="mwA-o">Model</span><span class="p" id="mwA-s">);</span> <span class="k" id="mwA-w">public</span><span class="w" id="mwA-0"> </span><span class="k" id="mwA-4">union</span><span class="w" id="mwA-8"> </span><span class="nf" id="mwA_A">Vehicle</span><span class="p" id="mwA_E">(</span><span class="n" id="mwA_I">Car</span><span class="p" id="mwA_M">,</span><span class="w" id="mwA_Q"> </span><span class="n" id="mwA_U">Bicycle</span><span class="p" id="mwA_Y">,</span><span class="w" id="mwA_c"> </span><span class="n" id="mwA_g">Bus</span><span class="p" id="mwA_k">);</span> <span class="n" id="mwA_o">Vehicle</span><span class="w" id="mwA_s"> </span><span class="n" id="mwA_w">car</span><span class="w" id="mwA_0"> </span><span class="o" id="mwA_4">=</span><span class="w" id="mwA_8"> </span><span class="k" id="mwBAA">new</span><span class="w" id="mwBAE"> </span><span class="n" id="mwBAI">Car</span><span class="p" id="mwBAM">(</span><span class="s" id="mwBAQ">"Tesla Model 3"</span><span class="p" id="mwBAU">);</span> <span class="n" id="mwBAY">Console</span><span class="p" id="mwBAc">.</span><span class="n" id="mwBAg">WriteLine</span><span class="p" id="mwBAk">(</span><span class="n" id="mwBAo">car</span><span class="p" id="mwBAs">.</span><span class="n" id="mwBAw">Value</span><span class="p" id="mwBA0">);</span><span class="w" id="mwBA4"> </span><span class="c1" id="mwBA8">// Car { Model = Tesla Model 3 }</span> <span class="n" id="mwBBA">Vehicle</span><span class="w" id="mwBBE"> </span><span class="n" id="mwBBI">bike</span><span class="w" id="mwBBM"> </span><span class="o" id="mwBBQ">=</span><span class="w" id="mwBBU"> </span><span class="k" id="mwBBY">new</span><span class="w" id="mwBBc"> </span><span class="n" id="mwBBg">Bicycle</span><span class="p" id="mwBBk">(</span><span class="s" id="mwBBo">"Giant Escape 3"</span><span class="p" id="mwBBs">);</span> <span class="n" id="mwBBw">Console</span><span class="p" id="mwBB0">.</span><span class="n" id="mwBB4">WriteLine</span><span class="p" id="mwBB8">(</span><span class="n" id="mwBCA">bike</span><span class="p" id="mwBCE">.</span><span class="n" id="mwBCI">Value</span><span class="p" id="mwBCM">);</span><span class="w" id="mwBCQ"> </span><span class="c1" id="mwBCU">// Bicycle { Model = Giant Escape 3 }</span> <span class="n" id="mwBCY">Vehicle</span><span class="w" id="mwBCc"> </span><span class="n" id="mwBCg">bus</span><span class="w" id="mwBCk"> </span><span class="o" id="mwBCo">=</span><span class="w" id="mwBCs"> </span><span class="k" id="mwBCw">new</span><span class="w" id="mwBC0"> </span><span class="n" id="mwBC4">Bus</span><span class="p" id="mwBC8">(</span><span class="s" id="mwBDA">"Volvo 9700"</span><span class="p" id="mwBDE">);</span> <span class="n" id="mwBDI">Console</span><span class="p" id="mwBDM">.</span><span class="n" id="mwBDQ">WriteLine</span><span class="p" id="mwBDU">(</span><span class="n" id="mwBDY">bus</span><span class="p" id="mwBDc">.</span><span class="n" id="mwBDg">Value</span><span class="p" id="mwBDk">);</span><span class="w" id="mwBDo"> </span><span class="c1" id="mwBDs">// Bus { Model = Volvo 9700 }</span> <span class="n" id="mwBDw">Vehicle</span><span class="w" id="mwBD0"> </span><span class="n" id="mwBD4">v</span><span class="w" id="mwBD8"> </span><span class="o" id="mwBEA">=</span><span class="w" id="mwBEE"> </span><span class="cm" id="mwBEI">/* some vehicle here */</span><span class="p" id="mwBEM">;</span> <span class="kt" id="mwBEQ">string</span><span class="w" id="mwBEU"> </span><span class="n" id="mwBEY">model</span><span class="w" id="mwBEc"> </span><span class="o" id="mwBEg">=</span><span class="w" id="mwBEk"> </span><span class="n" id="mwBEo">v</span><span class="w" id="mwBEs"> </span><span class="k" id="mwBEw">switch</span> <span class="p" id="mwBE0">{</span> <span class="w" id="mwBE4"> </span><span class="n" id="mwBE8">Car</span><span class="w" id="mwBFA"> </span><span class="n" id="mwBFE">c</span><span class="w" id="mwBFI"> </span><span class="o" id="mwBFM">=></span><span class="w" id="mwBFQ"> </span><span class="n" id="mwBFU">c</span><span class="p" id="mwBFY">.</span><span class="n" id="mwBFc">Model</span><span class="p" id="mwBFg">,</span> <span class="w" id="mwBFk"> </span><span class="n" id="mwBFo">Bicycle</span><span class="w" id="mwBFs"> </span><span class="n" id="mwBFw">bk</span><span class="w" id="mwBF0"> </span><span class="o" id="mwBF4">=></span><span class="w" id="mwBF8"> </span><span class="n" id="mwBGA">b</span><span class="p" id="mwBGE">.</span><span class="n" id="mwBGI">Model</span><span class="p" id="mwBGM">,</span> <span class="w" id="mwBGQ"> </span><span class="n" id="mwBGU">Bus</span><span class="w" id="mwBGY"> </span><span class="n" id="mwBGc">bs</span><span class="w" id="mwBGg"> </span><span class="o" id="mwBGk">=></span><span class="w" id="mwBGo"> </span><span class="n" id="mwBGs">bs</span><span class="p" id="mwBGw">.</span><span class="n" id="mwBG0">Model</span><span class="p" id="mwBG4">,</span> <span class="p" id="mwBG8">};</span>The default value of a union is null, but if all types in the union are non-nullable, then a switch expression need not check for null.
Java
Union types do not exist in Java, although they can be somewhat emulated using interfaces.
<span id="mwBHs"></span><span class="c1" id="mwBHw">// "Shape" can be thought of as a union of "Circle", "Rectangle",</span> <span class="c1" id="mwBH0">// and other types that implement "Shape"</span> <span class="c1" id="mwBH4">// we can explicitly restrict what is in the union using a sealed interface</span> <span class="kd" id="mwBH8">sealed</span><span class="w" id="mwBIA"> </span><span class="kd" id="mwBIE">interface</span> <span class="nc" id="mwBII">Shape</span><span class="w" id="mwBIM"> </span><span class="kd" id="mwBIQ">permits</span><span class="w" id="mwBIU"> </span><span class="n" id="mwBIY">Circle</span><span class="p" id="mwBIc">,</span><span class="w" id="mwBIg"> </span><span class="n" id="mwBIk">Rectangle</span><span class="w" id="mwBIo"> </span><span class="p" id="mwBIs">{}</span> <span class="kd" id="mwBIw">record</span> <span class="nc" id="mwBI0">Circle</span><span class="p" id="mwBI4">(</span><span class="kt" id="mwBI8">double</span><span class="w" id="mwBJA"> </span><span class="n" id="mwBJE">radius</span><span class="p" id="mwBJI">)</span><span class="w" id="mwBJM"> </span><span class="kd" id="mwBJQ">implements</span><span class="w" id="mwBJU"> </span><span class="n" id="mwBJY">Shape</span><span class="w" id="mwBJc"> </span><span class="p" id="mwBJg">{}</span> <span class="kd" id="mwBJk">record</span> <span class="nc" id="mwBJo">Rectangle</span><span class="p" id="mwBJs">(</span><span class="kt" id="mwBJw">double</span><span class="w" id="mwBJ0"> </span><span class="n" id="mwBJ4">width</span><span class="p" id="mwBJ8">,</span><span class="w" id="mwBKA"> </span><span class="kt" id="mwBKE">double</span><span class="w" id="mwBKI"> </span><span class="n" id="mwBKM">height</span><span class="p" id="mwBKQ">)</span><span class="w" id="mwBKU"> </span><span class="kd" id="mwBKY">implements</span><span class="w" id="mwBKc"> </span><span class="n" id="mwBKg">Shape</span><span class="w" id="mwBKk"> </span><span class="p" id="mwBKo">{}</span> <span class="kd" id="mwBKs">class</span> <span class="nc" id="mwBKw">Example</span><span class="w" id="mwBK0"> </span><span class="p" id="mwBK4">{</span> <span class="w" id="mwBK8"> </span><span class="kt" id="mwBLA">double</span><span class="w" id="mwBLE"> </span><span class="nf" id="mwBLI">area</span><span class="p" id="mwBLM">(</span><span class="n" id="mwBLQ">Shape</span><span class="w" id="mwBLU"> </span><span class="n" id="mwBLY">s</span><span class="p" id="mwBLc">)</span><span class="w" id="mwBLg"> </span><span class="p" id="mwBLk">{</span> <span class="w" id="mwBLo"> </span><span class="k" id="mwBLs">return</span><span class="w" id="mwBLw"> </span><span class="k" id="mwBL0">switch</span><span class="w" id="mwBL4"> </span><span class="p" id="mwBL8">(</span><span class="n" id="mwBMA">s</span><span class="p" id="mwBME">)</span><span class="w" id="mwBMI"> </span><span class="p" id="mwBMM">{</span> <span class="w" id="mwBMQ"> </span><span class="k" id="mwBMU">case</span><span class="w" id="mwBMY"> </span><span class="n" id="mwBMc">Circle</span><span class="p" id="mwBMg">(</span><span class="kt" id="mwBMk">double</span><span class="w" id="mwBMo"> </span><span class="n" id="mwBMs">r</span><span class="p" id="mwBMw">)</span><span class="w" id="mwBM0"> </span><span class="o" id="mwBM4">-></span><span class="w" id="mwBM8"> </span><span class="n" id="mwBNA">Math</span><span class="p" id="mwBNE">.</span><span class="na" id="mwBNI">PI</span><span class="w" id="mwBNM"> </span><span class="o" id="mwBNQ">*</span><span class="w" id="mwBNU"> </span><span class="n" id="mwBNY">r</span><span class="w" id="mwBNc"> </span><span class="o" id="mwBNg">*</span><span class="w" id="mwBNk"> </span><span class="n" id="mwBNo">r</span><span class="p" id="mwBNs">;</span> <span class="w" id="mwBNw"> </span><span class="k" id="mwBN0">case</span><span class="w" id="mwBN4"> </span><span class="n" id="mwBN8">Rectangle</span><span class="p" id="mwBOA">(</span><span class="kt" id="mwBOE">double</span><span class="w" id="mwBOI"> </span><span class="n" id="mwBOM">w</span><span class="p" id="mwBOQ">,</span><span class="w" id="mwBOU"> </span><span class="kt" id="mwBOY">double</span><span class="w" id="mwBOc"> </span><span class="n" id="mwBOg">h</span><span class="p" id="mwBOk">)</span><span class="w" id="mwBOo"> </span><span class="o" id="mwBOs">-></span><span class="w" id="mwBOw"> </span><span class="n" id="mwBO0">w</span><span class="w" id="mwBO4"> </span><span class="o" id="mwBO8">*</span><span class="w" id="mwBPA"> </span><span class="n" id="mwBPE">h</span><span class="p" id="mwBPI">;</span> <span class="w" id="mwBPM"> </span><span class="p" id="mwBPQ">};</span> <span class="w" id="mwBPU"> </span><span class="p" id="mwBPY">}</span> <span class="p" id="mwBPc">}</span>A catch clause can declare a union of multiple exception types. This syntax resembles union type syntax in other languages, but does not actually introduce a new type. The effective type of the exception parameter is the most specific common supertype of the alternatives. The catch clause only catches exceptions of the declared types, no other subclasses of the common supertype.
<span id="mwBQA"></span><span class="kd" id="mwBQE">class</span> <span class="nc" id="mwBQI">FooException</span><span class="w" id="mwBQM"> </span><span class="kd" id="mwBQQ">extends</span><span class="w" id="mwBQU"> </span><span class="n" id="mwBQY">RuntimeException</span><span class="w" id="mwBQc"> </span><span class="p" id="mwBQg">{</span> <span class="w" id="mwBQk"> </span><span class="n" id="mwBQo">String</span><span class="w" id="mwBQs"> </span><span class="nf" id="mwBQw">name</span><span class="p" id="mwBQ0">()</span><span class="w" id="mwBQ4"> </span><span class="p" id="mwBQ8">{</span> <span class="w" id="mwBRA"> </span><span class="k" id="mwBRE">return</span><span class="w" id="mwBRI"> </span><span class="s" id="mwBRM">"Foo"</span><span class="p" id="mwBRQ">;</span> <span class="w" id="mwBRU"> </span><span class="p" id="mwBRY">}</span> <span class="p" id="mwBRc">}</span> <span class="kd" id="mwBRg">class</span> <span class="nc" id="mwBRk">BarException</span><span class="w" id="mwBRo"> </span><span class="kd" id="mwBRs">extends</span><span class="w" id="mwBRw"> </span><span class="n" id="mwBR0">RuntimeException</span><span class="w" id="mwBR4"> </span><span class="p" id="mwBR8">{</span> <span class="w" id="mwBSA"> </span><span class="n" id="mwBSE">String</span><span class="w" id="mwBSI"> </span><span class="nf" id="mwBSM">name</span><span class="p" id="mwBSQ">()</span><span class="w" id="mwBSU"> </span><span class="p" id="mwBSY">{</span> <span class="w" id="mwBSc"> </span><span class="k" id="mwBSg">return</span><span class="w" id="mwBSk"> </span><span class="s" id="mwBSo">"Bar"</span><span class="p" id="mwBSs">;</span> <span class="w" id="mwBSw"> </span><span class="p" id="mwBS0">}</span> <span class="p" id="mwBS4">}</span> <span class="kt" id="mwBS8">void</span><span class="w" id="mwBTA"> </span><span class="nf" id="mwBTE">main</span><span class="p" id="mwBTI">()</span><span class="w" id="mwBTM"> </span><span class="p" id="mwBTQ">{</span> <span class="w" id="mwBTU"> </span><span class="k" id="mwBTY">try</span><span class="w" id="mwBTc"> </span><span class="p" id="mwBTg">{</span> <span class="w" id="mwBTk"> </span><span class="k" id="mwBTo">throw</span><span class="w" id="mwBTs"> </span><span class="n" id="mwBTw">Math</span><span class="p" id="mwBT0">.</span><span class="na" id="mwBT4">random</span><span class="p" id="mwBT8">()</span><span class="w" id="mwBUA"> </span><span class="o" id="mwBUE"><</span><span class="w" id="mwBUI"> </span><span class="mf" id="mwBUM">0.5</span><span class="w" id="mwBUQ"> </span><span class="o" id="mwBUU">?</span><span class="w" id="mwBUY"> </span><span class="k" id="mwBUc">new</span><span class="w" id="mwBUg"> </span><span class="n" id="mwBUk">FooException</span><span class="p" id="mwBUo">()</span><span class="w" id="mwBUs"> </span><span class="p" id="mwBUw">:</span><span class="w" id="mwBU0"> </span><span class="k" id="mwBU4">new</span><span class="w" id="mwBU8"> </span><span class="n" id="mwBVA">BarException</span><span class="p" id="mwBVE">();</span> <span class="w" id="mwBVI"> </span><span class="p" id="mwBVM">}</span><span class="w" id="mwBVQ"> </span><span class="k" id="mwBVU">catch</span><span class="w" id="mwBVY"> </span><span class="p" id="mwBVc">(</span><span class="n" id="mwBVg">FooException</span><span class="w" id="mwBVk"> </span><span class="o" id="mwBVo">|</span><span class="w" id="mwBVs"> </span><span class="n" id="mwBVw">BarException</span><span class="w" id="mwBV0"> </span><span class="n" id="mwBV4">e</span><span class="p" id="mwBV8">)</span><span class="w" id="mwBWA"> </span><span class="p" id="mwBWE">{</span> <span class="w" id="mwBWI"> </span><span class="c1" id="mwBWM">// e has type RuntimeException, the common supertype of FooException and BarException</span> <span class="w" id="mwBWQ"> </span><span class="n" id="mwBWU">System</span><span class="p" id="mwBWY">.</span><span class="na" id="mwBWc">out</span><span class="p" id="mwBWg">.</span><span class="na" id="mwBWk">println</span><span class="p" id="mwBWo">(</span><span class="n" id="mwBWs">e</span><span class="p" id="mwBWw">);</span> <span class="w" id="mwBW0"> </span><span class="n" id="mwBW4">e</span><span class="p" id="mwBW8">.</span><span class="na" id="mwBXA">printStackTrace</span><span class="p" id="mwBXE">();</span> <span class="w" id="mwBXI"> </span><span class="c1" id="mwBXM">// System.out.println(e.name());</span> <span class="w" id="mwBXQ"> </span><span class="c1" id="mwBXU">// Because there is no name() method in RuntimeException, this fails to compile</span> <span class="w" id="mwBXY"> </span><span class="p" id="mwBXc">}</span> <span class="p" id="mwBXg">}</span>PHP
Union types were introduced in PHP 8.0. The values are implicitly "tagged" with a type by the language, and may be retrieved by "gettype()".
<span id="mwBYE"></span><span class="k" id="mwBYI">class</span> <span class="nc" id="mwBYM">Example</span> <span class="p" id="mwBYQ">{</span> <span class="k" id="mwBYU">private</span> <span class="nx" id="mwBYY">int</span><span class="o" id="mwBYc">|</span><span class="nx" id="mwBYg">float</span> <span class="nv" id="mwBYk">$foo</span><span class="p" id="mwBYo">;</span> <span class="k" id="mwBYs">public</span> <span class="k" id="mwBYw">function</span> <span class="nf" id="mwBY0">squareAndAdd</span><span class="p" id="mwBY4">(</span><span class="nx" id="mwBY8">float</span><span class="o" id="mwBZA">|</span><span class="nx" id="mwBZE">int</span> <span class="nv" id="mwBZI">$bar</span><span class="p" id="mwBZM">)</span><span class="o" id="mwBZQ">:</span> <span class="nx" id="mwBZU">int</span><span class="o" id="mwBZY">|</span><span class="nx" id="mwBZc">float</span> <span class="p" id="mwBZg">{</span> <span class="k" id="mwBZk">return</span> <span class="nv" id="mwBZo">$bar</span> <span class="o" id="mwBZs">**</span> <span class="mi" id="mwBZw">2</span> <span class="o" id="mwBZ0">+</span> <span class="nv" id="mwBZ4">$this</span><span class="o" id="mwBZ8">-></span><span class="na" id="mwBaA">foo</span><span class="p" id="mwBaE">;</span> <span class="p" id="mwBaI">}</span> <span class="p" id="mwBaM">}</span>Python
Support for typing was introduced in Python 3.5. The new syntax for union types were introduced in Python 3.10.
<span id="mwBbA"></span><span class="kn" id="mwBbE">from</span><span class="w" id="mwBbI"> </span><span class="nn" id="mwBbM">typing</span><span class="w" id="mwBbQ"> </span><span class="kn" id="mwBbU">import</span> <span class="n" id="mwBbY">Union</span> <span class="k" id="mwBbc">class</span><span class="w" id="mwBbg"> </span><span class="nc" id="mwBbk">Example</span><span class="p" id="mwBbo">:</span> <span class="n" id="mwBbs">foo</span><span class="p" id="mwBbw">:</span> <span class="nb" id="mwBb0">int</span> <span class="o" id="mwBb4">=</span> <span class="mi" id="mwBb8">0</span> <span class="c1" id="mwBcA"># old style:</span> <span class="k" id="mwBcE">def</span><span class="w" id="mwBcI"> </span><span class="nf" id="mwBcM">square_and_add</span><span class="p" id="mwBcQ">(</span><span class="bp" id="mwBcU">self</span><span class="p" id="mwBcY">,</span> <span class="n" id="mwBcc">bar</span><span class="p" id="mwBcg">:</span> <span class="n" id="mwBck">Union</span><span class="p" id="mwBco">[</span><span class="nb" id="mwBcs">int</span><span class="p" id="mwBcw">,</span> <span class="nb" id="mwBc0">float</span><span class="p" id="mwBc4">])</span> <span class="o" id="mwBc8">-></span> <span class="n" id="mwBdA">Union</span><span class="p" id="mwBdE">[</span><span class="nb" id="mwBdI">int</span><span class="p" id="mwBdM">,</span> <span class="nb" id="mwBdQ">float</span><span class="p" id="mwBdU">]:</span> <span class="k" id="mwBdY">return</span> <span class="n" id="mwBdc">bar</span> <span class="o" id="mwBdg">**</span> <span class="mi" id="mwBdk">2</span> <span class="o" id="mwBdo">+</span> <span class="bp" id="mwBds">self</span><span class="o" id="mwBdw">.</span><span class="n" id="mwBd0">foo</span> <span class="c1" id="mwBd4"># new style:</span> <span class="k" id="mwBd8">def</span><span class="w" id="mwBeA"> </span><span class="nf" id="mwBeE">square_and_add</span><span class="p" id="mwBeI">(</span><span class="bp" id="mwBeM">self</span><span class="p" id="mwBeQ">,</span> <span class="n" id="mwBeU">bar</span><span class="p" id="mwBeY">:</span> <span class="nb" id="mwBec">int</span> <span class="o" id="mwBeg">|</span> <span class="nb" id="mwBek">float</span><span class="p" id="mwBeo">)</span> <span class="o" id="mwBes">-></span> <span class="nb" id="mwBew">int</span> <span class="o" id="mwBe0">|</span> <span class="nb" id="mwBe4">float</span><span class="p" id="mwBe8">:</span> <span class="k" id="mwBfA">return</span> <span class="n" id="mwBfE">bar</span> <span class="o" id="mwBfI">**</span> <span class="mi" id="mwBfM">2</span> <span class="o" id="mwBfQ">+</span> <span class="bp" id="mwBfU">self</span><span class="o" id="mwBfY">.</span><span class="n" id="mwBfc">foo</span>
TypeScript
Union types are supported in TypeScript. When TypeScript code is transpiled to JavaScript, all type-related information is lost. This means that there is no one way to identify the type of a value at runtime as it appears in TypeScript. However, all JavaScript values are implicitly "tagged" with a type by the language, which may be retrieved using the typeof operator for primitive values and the instanceof operator for classes. Because JavaScript uses a dynamic type system, how operations such as addition or indexing will behave is determined at runtime based on the type of the value. This means if all members of a union type support a given operation, no additional work has to be done to perform said operation.
<span id="mwBgk"></span><span class="kd" id="mwBgo">function</span><span class="w" id="mwBgs"> </span><span class="nx" id="mwBgw">length</span><span class="p" id="mwBg0">(</span><span class="nx" id="mwBg4">v</span><span class="o" id="mwBg8">:</span><span class="w" id="mwBhA"> </span><span class="kt" id="mwBhE">string</span><span class="w" id="mwBhI"> </span><span class="o" id="mwBhM">|</span><span class="w" id="mwBhQ"> </span><span class="nx" id="mwBhU">any</span><span class="p" id="mwBhY">[])</span><span class="w" id="mwBhc"> </span><span class="p" id="mwBhg">{</span> <span class="w" id="mwBhk"> </span><span class="c1" id="mwBho">// because both strings and arrays have a "length" property, we can use it without having to figure out the actual type of v.</span> <span class="w" id="mwBhs"> </span><span class="k" id="mwBhw">return</span><span class="w" id="mwBh0"> </span><span class="nx" id="mwBh4">v</span><span class="p" id="mwBh8">.</span><span class="nx" id="mwBiA">length</span><span class="p" id="mwBiE">;</span> <span class="p" id="mwBiI">}</span> <span class="kd" id="mwBiM">function</span><span class="w" id="mwBiQ"> </span><span class="nx" id="mwBiU">containsTheLetterA</span><span class="p" id="mwBiY">(</span><span class="nx" id="mwBic">v</span><span class="o" id="mwBig">:</span><span class="w" id="mwBik"> </span><span class="kt" id="mwBio">string</span><span class="w" id="mwBis"> </span><span class="o" id="mwBiw">|</span><span class="w" id="mwBi0"> </span><span class="kt" id="mwBi4">string</span><span class="p" id="mwBi8">[]</span><span class="w" id="mwBjA"> </span><span class="o" id="mwBjE">|</span><span class="w" id="mwBjI"> </span><span class="kt" id="mwBjM">number</span><span class="p" id="mwBjQ">)</span><span class="w" id="mwBjU"> </span><span class="p" id="mwBjY">{</span> <span class="w" id="mwBjc"> </span><span class="c1" id="mwBjg">// sometimes, it is important to know the exact type of a value.</span> <span class="w" id="mwBjk"> </span><span class="k" id="mwBjo">if</span><span class="w" id="mwBjs"> </span><span class="p" id="mwBjw">(</span><span class="ow" id="mwBj0">typeof</span><span class="w" id="mwBj4"> </span><span class="nx" id="mwBj8">v</span><span class="w" id="mwBkA"> </span><span class="o" id="mwBkE">===</span><span class="w" id="mwBkI"> </span><span class="s2" id="mwBkM">"string"</span><span class="p" id="mwBkQ">)</span><span class="w" id="mwBkU"> </span><span class="p" id="mwBkY">{</span> <span class="w" id="mwBkc"> </span><span class="k" id="mwBkg">return</span><span class="w" id="mwBkk"> </span><span class="nx" id="mwBko">v</span><span class="p" id="mwBks">.</span><span class="nx" id="mwBkw">includes</span><span class="p" id="mwBk0">(</span><span class="s2" id="mwBk4">"a"</span><span class="p" id="mwBk8">);</span> <span class="w" id="mwBlA"> </span><span class="p" id="mwBlE">}</span><span class="w" id="mwBlI"> </span><span class="k" id="mwBlM">else</span><span class="w" id="mwBlQ"> </span><span class="k" id="mwBlU">if</span><span class="w" id="mwBlY"> </span><span class="p" id="mwBlc">(</span><span class="nx" id="mwBlg">v</span><span class="w" id="mwBlk"> </span><span class="ow" id="mwBlo">instanceof</span><span class="w" id="mwBls"> </span><span class="nb" id="mwBlw">Array</span><span class="p" id="mwBl0">)</span><span class="w" id="mwBl4"> </span><span class="p" id="mwBl8">{</span> <span class="w" id="mwBmA"> </span><span class="c1" id="mwBmE">// because v is an Array, we want to check if any element includes the letter A.</span> <span class="w" id="mwBmI"> </span><span class="k" id="mwBmM">return</span><span class="w" id="mwBmQ"> </span><span class="nx" id="mwBmU">v</span><span class="p" id="mwBmY">.</span><span class="nx" id="mwBmc">some</span><span class="p" id="mwBmg">((</span><span class="nx" id="mwBmk">element</span><span class="p" id="mwBmo">)</span><span class="w" id="mwBms"> </span><span class="p" id="mwBmw">=></span><span class="w" id="mwBm0"> </span><span class="nx" id="mwBm4">element</span><span class="p" id="mwBm8">.</span><span class="nx" id="mwBnA">includes</span><span class="p" id="mwBnE">(</span><span class="s2" id="mwBnI">"a"</span><span class="p" id="mwBnM">));</span> <span class="w" id="mwBnQ"> </span><span class="p" id="mwBnU">}</span><span class="w" id="mwBnY"> </span><span class="k" id="mwBnc">else</span><span class="w" id="mwBng"> </span><span class="p" id="mwBnk">{</span> <span class="w" id="mwBno"> </span><span class="c1" id="mwBns">// because we know it isn't an array or string, it must be a number.</span> <span class="w" id="mwBnw"> </span><span class="c1" id="mwBn0">// numbers don't ever contain the letter a.</span> <span class="w" id="mwBn4"> </span><span class="k" id="mwBn8">return</span><span class="w" id="mwBoA"> </span><span class="kc" id="mwBoE">false</span><span class="p" id="mwBoI">;</span> <span class="w" id="mwBoM"> </span><span class="p" id="mwBoQ">}</span> <span class="p" id="mwBoU">}</span>Rust
Tagged unions in Rust use the enum keyword, and can contain tuple and struct variants:
<span id="mwBow"></span><span class="k" id="mwBo0">enum</span><span class="w" id="mwBo4"> </span><span class="nc" id="mwBo8">Foo</span><span class="w" id="mwBpA"> </span><span class="p" id="mwBpE">{</span> <span class="w" id="mwBpI"> </span><span class="n" id="mwBpM">Bar</span><span class="p" id="mwBpQ">(</span><span class="kt" id="mwBpU">i32</span><span class="p" id="mwBpY">),</span> <span class="w" id="mwBpc"> </span><span class="n" id="mwBpg">Baz</span><span class="w" id="mwBpk"> </span><span class="p" id="mwBpo">{</span><span class="w" id="mwBps"> </span><span class="n" id="mwBpw">x</span><span class="p" id="mwBp0">:</span><span class="w" id="mwBp4"> </span><span class="nb" id="mwBp8">String</span><span class="p" id="mwBqA">,</span><span class="w" id="mwBqE"> </span><span class="n" id="mwBqI">y</span><span class="p" id="mwBqM">:</span><span class="w" id="mwBqQ"> </span><span class="kt" id="mwBqU">i32</span><span class="w" id="mwBqY"> </span><span class="p" id="mwBqc">},</span> <span class="p" id="mwBqg">}</span>Untagged unions in Rust use the union keyword:
<span id="mwBq4"></span><span class="k" id="mwBq8">union</span><span class="w" id="mwBrA"> </span><span class="nc" id="mwBrE">Foo</span><span class="w" id="mwBrI"> </span><span class="p" id="mwBrM">{</span> <span class="w" id="mwBrQ"> </span><span class="n" id="mwBrU">bar</span><span class="p" id="mwBrY">:</span><span class="w" id="mwBrc"> </span><span class="kt" id="mwBrg">i32</span><span class="p" id="mwBrk">,</span> <span class="w" id="mwBro"> </span><span class="n" id="mwBrs">baz</span><span class="p" id="mwBrw">:</span><span class="w" id="mwBr0"> </span><span class="kt" id="mwBr4">bool</span><span class="p" id="mwBr8">,</span> <span class="p" id="mwBsA">}</span>Reading from the fields of an untagged union results in undefined behavior if the data in the union is not valid as the type of the field, and thus requires an unsafe block:
<span id="mwBsc"></span><span class="kd" id="mwBsg">let</span><span class="w" id="mwBsk"> </span><span class="n" id="mwBso">x</span><span class="w" id="mwBss"> </span><span class="o" id="mwBsw">=</span><span class="w" id="mwBs0"> </span><span class="n" id="mwBs4">Foo</span><span class="w" id="mwBs8"> </span><span class="p" id="mwBtA">{</span><span class="w" id="mwBtE"> </span><span class="n" id="mwBtI">bar</span><span class="p" id="mwBtM">:</span><span class="w" id="mwBtQ"> </span><span class="mi" id="mwBtU">10</span><span class="w" id="mwBtY"> </span><span class="p" id="mwBtc">};</span> <span class="kd" id="mwBtg">let</span><span class="w" id="mwBtk"> </span><span class="n" id="mwBto">y</span><span class="w" id="mwBts"> </span><span class="o" id="mwBtw">=</span><span class="w" id="mwBt0"> </span><span class="k" id="mwBt4">unsafe</span><span class="w" id="mwBt8"> </span><span class="p" id="mwBuA">{</span><span class="w" id="mwBuE"> </span><span class="n" id="mwBuI">x</span><span class="p" id="mwBuM">.</span><span class="n" id="mwBuQ">bar</span><span class="w" id="mwBuU"> </span><span class="p" id="mwBuY">};</span><span class="w" id="mwBuc"> </span><span class="c1" id="mwBug">// This will set y to 10, and does not result in undefined behavior.</span> <span class="kd" id="mwBuk">let</span><span class="w" id="mwBuo"> </span><span class="n" id="mwBus">z</span><span class="w" id="mwBuw"> </span><span class="o" id="mwBu0">=</span><span class="w" id="mwBu4"> </span><span class="k" id="mwBu8">unsafe</span><span class="w" id="mwBvA"> </span><span class="p" id="mwBvE">{</span><span class="w" id="mwBvI"> </span><span class="n" id="mwBvM">x</span><span class="p" id="mwBvQ">.</span><span class="n" id="mwBvU">baz</span><span class="w" id="mwBvY"> </span><span class="p" id="mwBvc">};</span><span class="w" id="mwBvg"> </span><span class="c1" id="mwBvk">// This results in undefined behavior, as the value stored in x is not a valid bool.</span>
