From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM autolearn=unavailable autolearn_force=no version=3.4.4 X-Received: by 10.224.29.76 with SMTP id p12mr3503411qac.5.1372876532885; Wed, 03 Jul 2013 11:35:32 -0700 (PDT) X-Received: by 10.182.104.10 with SMTP id ga10mr18026obb.23.1372876532743; Wed, 03 Jul 2013 11:35:32 -0700 (PDT) Path: border1.nntp.dca3.giganews.com!border3.nntp.dca.giganews.com!border1.nntp.dca.giganews.com!nntp.giganews.com!t19no9479qam.0!news-out.google.com!f7ni806qai.0!nntp.google.com!t19no9488qam.0!postnews.google.com!glegroupsg2000goo.googlegroups.com!not-for-mail Newsgroups: comp.lang.ada Date: Wed, 3 Jul 2013 11:35:32 -0700 (PDT) In-Reply-To: <0606a658-9816-4611-84dd-4f999bf6018e@googlegroups.com> Complaints-To: groups-abuse@google.com Injection-Info: glegroupsg2000goo.googlegroups.com; posting-host=69.20.190.126; posting-account=lJ3JNwoAAAAQfH3VV9vttJLkThaxtTfC NNTP-Posting-Host: 69.20.190.126 References: <0606a658-9816-4611-84dd-4f999bf6018e@googlegroups.com> User-Agent: G2/1.0 MIME-Version: 1.0 Message-ID: <5f82ded8-fd50-41fa-8c0e-c16203fb032f@googlegroups.com> Subject: Re: Variant record limitation - what's a better solution? From: Shark8 Injection-Date: Wed, 03 Jul 2013 18:35:32 +0000 Content-Type: text/plain; charset=ISO-8859-1 X-Original-Bytes: 3678 Xref: number.nntp.dca.giganews.com comp.lang.ada:182256 Date: 2013-07-03T11:35:32-07:00 List-Id: On Wednesday, July 3, 2013 1:52:12 AM UTC-6, Peter Brooks wrote: > > Here's an example: > > type > > my_object(X : size_type) is > record > name : string(1..80); > case X is > when small => Y : small_type; -- line 20 > when medium => Y : medium_type; -- line 21 > when large => Y : large_type; -- line 22 > end case; > > end record; > > > I was hoping to have a different type depending on the case, but this doesn't seem allowed. What would achieve this? Well, you can use subtypes as you might originally think (but there's a bit of a hiccup) -- example: type small_type is range 0..2**8-1; type medium_type is range 0..2**16-1; type large_type is range 0..2**32-1; type size_type is ( small, medium, large ); type my_object(Size : size_type) is record name : string(1..80); case Size is when small => small_data : small_type; when medium => med_data : medium_type; when large => large_data : large_type; end case; end record; subtype small_object is my_object( Size => small ); subtype medium_object is my_object( Size => medium ); subtype large_object is my_object( Size => large ); -- Using Ada 2012 expression-functions for brevity. function Get_Data( Item : in small_object ) return small_type is ( Item.small_data ); function Get_Data( Item : in medium_object ) return medium_type is ( Item.med_data ); function Get_Data( Item : in large_object ) return large_type is ( Item.large_data ); J : my_object:= ( Size => small, small_data => 128, Name => ('B','o','b', others => ASCII.NUL) ); K : constant integer := Integer( Get_Data( J ) ); Now the assignment to K shows the problem with this approach, as the compiler points out: ambiguous operand in conversion. This is because even though the compiler knows the types involved a differing subtypes it cannot [generally] distinguish between them like it would with a case-statement's case coverage. (That is, subtypes in-general aren't mutually exclusive.) At this point there are two obvious ways to go about addressing this: 1) add a qualification: e.g. Integer( Small'(Get_Data( J )) ); -- The above will make the assignment to K work. 2) go to a tagged record-type and use standard OO-methodologies there.