Previous | Table of Contents | Next |
Structs, unions and enums are the constructed types. Their syntax is presented in this section:
(48) <constr_type_spec> ::= <struct_type>| <union_type>| <enum_type>
(99) <constr_forward_decl> ::= “struct? <identifier>| “union? <identifier>
(42) <type_dcl> ::= “typedef? <type_declarator> | <struct_type> | <union_type> | <enum_type>
| “native? <simple_declarator> | <constr_forward_decl>
3.11.2.1 Structures
The syntax for struct type is
(69) <struct_type> ::= “struct? <identifier> “{? <member_list> “}?
(70) <member_list> ::= <member>+
(71) <member> ::= <type_spec> <declarators> “;?
The <identifier> in <struct_type> defines a new legal type. Structure types may also be named using a typedef declaration.
Name scoping rules require that the member declarators in a particular structure be unique. The value of a struct is the value
of all of its members.
3.11.2.2 Discriminated Unions
The discriminated union syntax is:
(72) <union_type> ::= “union? <identifier> “switch? “(? <switch_type_spec> “)?“{? <switch_body> “}?
(73) <switch_type_spec> ::= <integer_type>| <char_type>| <boolean_type>| <enum_type>| <scoped_name>
(74) <switch_body> ::= <case>+
(75) <case> ::= <case_label>+ <element_spec> “;?
(76) <case_label> ::= “case? <const_exp> “:?| “default? “:?
(77) <element_spec> ::= <type_spec> <declarator>
OMG IDL unions are a cross between the C union and switch statements. IDL unions must be discriminated; that is, the union
header must specify a typed tag field that determines which union member to use for the current instance of a call. The <identifier>
following the union keyword defines a new legal type. Union types may also be named using a typedef declaration. The <const_exp>
in a <case_label> must be consistent with the <switch_type_spec>. A default case can appear at most once. The <scoped_name>
in the <switch_type_spec> production must be a previously defined integer, char, boolean or enum type.
Case labels must match or be automatically castable to the defined type of the discriminator. Name scoping rules require that
the element declarators in a particular union be unique. If the <switch_type_spec> is an <enum_type>, the identifier for the
enumeration is in the scope of the union; as a result, it must be distinct from the element declarators.
It is not required that all possible values of the union discriminator be listed in the <switch_body>. The value of a union
is the value of the discriminator together with one of the following:
• If the discriminator value was explicitly listed in a case statement, the value of the element associated with that case statement;
• If a default case label was specified, the value of the element associated with the default case label;
• No additional value.
The values of the constant expressions for the case labels of a single union definition must be distinct. A union type can
contain a default label only where the values given in the non-default labels do not cover the entire range of the union's
discriminant type.
Access to the discriminator and the related element is language-mapping dependent.
Note – While any ISO Latin-1 (8859.1) IDL character literal may be used in a <case_label> in a union definition whose discriminator
type is char, not all of these characters are present in all transmission code sets that may be negotiated by GIOP or in all
native code sets that may be used by implementation language compilers and runtimes. When an attempt is made to marshal to
CDR a union whose discriminator value of char type is not available in the negotiated transmission code set, or to demarshal
from CDR a union whose discriminator value of char type is not available in the native code set, a DATA_CONVERSION system
exception is raised. Therefore, to ensure portability and interoperability, care must be exercised when assigning the <case_label>
for a union member whose discriminator type is char. Due to these issues, use of char types as the discriminator type for
unions is not recommended.
3.11.2.3 Constructed Recursive Types and IForward Declarations
The IDL syntax allows the generation of recursive structures and unions via members that have a sequence type. The element
type of a recursive sequence struct or union member must identify a struct, union, or valuetype. (A valuetype is allowed to
have a member of its own type either directly or indirectly through a member of a constructed
type—see Section 3.9.1.6, “Value Type Example,? on page 3-28.) For example, the
following is legal:
struct Foo { long value; sequence<Foo> chain; // Deprecated (see
Section 3.11.6)
}
See Section 3.11.3.1, “Sequences,? on page 3-44 for details of the
sequence template type.
IDL supports recursive types via a forward declaration for structures and unions (as
well as for valuetypes—see Section 3.9.1.6, “Value Type Example,? on page 3-28).
Because anonymous types are deprecated (see Section 3.11.6, “Deprecated Anonymous
Types,? on page 3-47), the previous example is better written as:
struct Foo; // Forward declarationtypedef sequence<Foo> FooSeq;struct Foo {
long value;
FooSeq chain; };
The forward declaration for the structure enables the definition of the sequence type FooSeq, which is used as the type of
the recursive member.
Forward declarations are legal for structures and unions.A structure or union type is termed incomplete until its full definition
is provided; that is, until the scope of the structure or union definition is closed by a terminating "}". For example:
struct Foo; // Introduces Foo type name,
// Foo is incomplete now
// ... struct Foo {
// ... }; // Foo is complete at this point
If a structure or union is forward declared, a definition of that structure or union must follow the forward declaration in
the same source file. Compilers shall issue a diagnostic if this rule is violated. Multiple forward declarations of the same
structure or union are legal.
If a recursive structure or union member is used, sequence members that are recursive must refer to an incomplete type currently
under definition. For example
struct Foo; // Forward declarationtypedef sequence<Foo> FooSeq;struct Bar {
long value;
FooSeq chain; //Illegal, Foo is not an enclosing struct or union };
Compilers shall issue a diagnostic if this rule is violated.
Recursive definitions can span multiple levels. For example:
union Bar; // Forward declaration typedef sequence<Bar> BarSeq; union Bar switch(long) { // Define incomplete union
case 0:
long l_mem; |
|||||
case 1: | |||||
struct Foo { | |||||
double d_mem; | |||||
BarSeq nested; | // OK, recurse on enclosing | ||||
// incomplete type | |||||
} s_mem; | |||||
}; |
An incomplete type can only appear as the element type of a sequence definition. A sequence with incomplete element type is
termed an incomplete sequence type:
struct Foo; // Forward declaration typedef sequence<Foo> FooSeq; // incomplete
An incomplete sequence type can appear only as the element type of another sequence, or as the member type of a structure
or union definition. For example:
struct Foo; // Forward declaration typedef sequence<Foo> FooSeq; // OK typedef sequence<FooSeq> FooTree; // OK
interface I { FooSeq op1(); // Illegal, FooSeq is incomplete void op2( // Illegal, FooTree is incomplete
in FooTree t ); };
struct Foo { // Provide definition of Foo long l_mem; FooSeq chain; // OK FooTree tree; // OK
};
interface J { FooSeq op1(); // OK, FooSeq is complete void op2(
in FooTree t // OK, FooTree is complete ); };
Compilers shall issue a diagnostic if this rule is violated.
3.11.2.4 Enumerations
Enumerated types consist of ordered lists of identifiers. The syntax is:
(78) <enum_type> ::= “enum? <identifier> “{? <enumerator> { “,? <enumerator> }∗ “}?
(79) <enumerator> ::= <identifier>
A maximum of 232 identifiers may be specified in an enumeration; as such, the enumerated names must be mapped to a native
data type capable of representing a maximally-sized enumeration. The order in which the identifiers are named in the specification
of an enumeration defines the relative order of the identifiers. Any language mapping that permits two enumerators to be compared
or defines successor/predecessor functions on enumerators must conform to this ordering relation. The <identifier> following
the enum keyword defines a new legal type. Enumerated types may also be named using a typedef declaration.