Previous Table of Contents Next


3.11.2 Constructed Types


   Structs, unions and enums are the constructed types. Their syntax is presented in this section:

   3.11.2.1 Structures

   The syntax for struct type is

   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:

   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:

   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:

   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.