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 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,196864e6c216ca4f X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2003-09-24 16:44:21 PST Path: archiver1.google.com!news1.google.com!newsfeed.stanford.edu!logbridge.uoregon.edu!arclight.uoregon.edu!wn13feed!wn11feed!worldnet.att.net!204.127.198.203!attbi_feed3!attbi_feed4!attbi.com!rwcrnsc53.POSTED!not-for-mail Message-ID: <3F722C53.9020808@attbi.com> From: "Robert I. Eachus" User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0.2) Gecko/20021120 Netscape/7.01 X-Accept-Language: en-us, en MIME-Version: 1.0 Newsgroups: comp.lang.ada Subject: Re: How to Emulate C++ Macro with Static Local Variable? References: Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit NNTP-Posting-Host: 24.34.139.183 X-Complaints-To: abuse@comcast.net X-Trace: rwcrnsc53 1064447061 24.34.139.183 (Wed, 24 Sep 2003 23:44:21 GMT) NNTP-Posting-Date: Wed, 24 Sep 2003 23:44:21 GMT Organization: Comcast Online Date: Wed, 24 Sep 2003 23:44:21 GMT Xref: archiver1.google.com comp.lang.ada:42868 Date: 2003-09-24T23:44:21+00:00 List-Id: taashlo@sandia.gov wrote: > Hello, > > I'm trying to port a small C++ library to Ada95. Most of it is going > quite well in that the Ada implementation is smaller, simpler, and > easier to follow than the C++ implementation. But I've ran into a > hurdle with the following C++ construction: > > class Test { > ... > protected: > struct s { > int data[8]; > }; > ... > void bar(s *t, int foo); > #define BAR(foo_) if (1) { \ > static s t_; \ > bar(&t_, foo_);\ > } else ((void)0) > ... > }; > > What happens is that when you do this: > > BAR(10); > > it expands to this: > > if (1) { > static s t_; > bar(&t_, 10); > } else ((void)0); > > This, in effect, creates a (hidden) static local variable for each call > to bar(). This static variable (actually a structure, t_) is used to > cache information for each unique call to bar() such that subsequent > calls from that location can be processed *much* faster. > > For instance, the following code would create three of the hidden local > variables: > > for (int i = 0; i < 55; ++i) { > switch (wozit()) { > case 1: BAR(10); break; > case 2: BAR(20); break; > case 3: BAR(30); break; > } > } > > The first time each BAR() is encountered, it does the full processing, > but subsequent calls to the *same* BAR() used it's unique cached > information and go much faster. > > Any ideas on how I can achieve this with Ada95? Wild, I'm going to give you "ideas," and let you implement one of them. First, the normal way to implement this in Ada would be to break the action into a generic instantiation followed by a call of the instantiated generic. But if you want to follow that pattern here it gets tricky to wrap it in a generic. You would need a subprogram access type declared at an outer level, the generic instantiation would create a procedure and pass back the access value for subsequent calls. The fast way to implement this of course is to use self-modifying code. Ugh! You can manage this with subprogram parameters. The first call goes to the 'generic' version which returns among other things the new address to call. Sort of: procedure Subp is type Subprogram_Record; type Subprogram_Pointer is access procedure(X: in Integer; P: in out Subprogram_Record); type Subprogram_Record is record SP: Subprogram_Pointer; end record; procedure Test (X: in Integer; P: in out Subprogram_Record) is begin null; end; Bar_Pointer: constant Subprogram_Record := (SP => Test'Access); Local_Pointer: Subprogram_Record := Bar_Pointer; begin Local_Pointer.SP.all(3, Local_Pointer); end Subp; This code is a bit ugly, but it does compile. And since Bar_Pointer is a constant, you can't accidently pass it to Test. There might be a cleaner cleverer way to do it, but this works. The cleanest option may be to run your code through a preprocessor and use a similar macro. -- Robert I. Eachus Ryan gunned down the last of his third white wine and told himself it would all be over in a few minutes. One thing he'd learned from Operation Beatrix: This field work wasn't for him. --from Red Rabbit by Tom Clancy.