comp.lang.ada
 help / color / mirror / Atom feed
* generic function and overloading
@ 2007-10-18  7:28 eliben
  2007-10-18  8:18 ` Jean-Pierre Rosen
                   ` (6 more replies)
  0 siblings, 7 replies; 14+ messages in thread
From: eliben @ 2007-10-18  7:28 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="iso-8859-8-i", Size: 997 bytes --]

Hello,

I have a few "hardware" types, for example uint16 and uint32. And I
want to write a functions that will set or clear bits of such types.
For example:

function Bit_Set(word: uint16; bitn: natural) return uint16;

function Bit_Set(word: uint16; bitn: natural) return uint16 is
  mask: uint16 := 2**bitn;
begin
  return word or mask;
end Bit_Set;

However, I realize that such a function would be almost completely
duplicated for the uint32 type. In C++ I would probably define it as a
template on the type of the word, and the compiler would do the job
for me. In Ada, however, when using generics it doesn't seem I can
leave the same function name for all types (as I would do in
overloading). I can define a generic Bit_Set, but then I have to
specialize it for uin16 and uint32 with different function names. Is
there any way I could combine the effects of generics and overloading
and get a single Bit_Set for all my types without writing the code N
times ?

P.S. Ada95

Thanks,
Eli




^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: generic function and overloading
  2007-10-18  7:28 generic function and overloading eliben
@ 2007-10-18  8:18 ` Jean-Pierre Rosen
  2007-10-18  9:31 ` Dmitry A. Kazakov
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: Jean-Pierre Rosen @ 2007-10-18  8:18 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=ISO-8859-8-I; format=flowed, Size: 1038 bytes --]

eliben a e'crit :
> [...] In Ada, however, when using generics it doesn't seem I can
> leave the same function name for all types (as I would do in
> overloading). I can define a generic Bit_Set, but then I have to
> specialize it for uin16 and uint32 with different function names. Is
> there any way I could combine the effects of generics and overloading
> and get a single Bit_Set for all my types without writing the code N
> times ?
> 
You should give the exact specification of your generic and of your 
instantiations to get a precise answer, but here is a wild guess at what 
is happenning:

The *generic* cannot have the same name as the instantiations. However, 
different *instantiations* can have the same name, provided the 
resulting functions have different profiles. In short, call your generic 
"Generic_Bit_Set", and then you can call all instantiations "Bit_Set".

-- 
---------------------------------------------------------
            J-P. Rosen (rosen@adalog.fr)
Visit Adalog's web site at http://www.adalog.fr



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: generic function and overloading
  2007-10-18  7:28 generic function and overloading eliben
  2007-10-18  8:18 ` Jean-Pierre Rosen
@ 2007-10-18  9:31 ` Dmitry A. Kazakov
  2007-10-18  9:33   ` Dmitry A. Kazakov
  2007-10-18 10:32 ` Georg Bauhaus
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 14+ messages in thread
From: Dmitry A. Kazakov @ 2007-10-18  9:31 UTC (permalink / raw)


On 18 Oct 2007 00:28:38 -0700, eliben wrote:

> I have a few "hardware" types, for example uint16 and uint32. And I
> want to write a functions that will set or clear bits of such types.
> For example:
> 
> function Bit_Set(word: uint16; bitn: natural) return uint16;
> 
> function Bit_Set(word: uint16; bitn: natural) return uint16 is
>   mask: uint16 := 2**bitn;
> begin
>   return word or mask;
> end Bit_Set;

Bit_Set (X, Natural'Last)?

> However, I realize that such a function would be almost completely
> duplicated for the uint32 type. In C++ I would probably define it as a
> template on the type of the word, and the compiler would do the job
> for me. In Ada, however, when using generics it doesn't seem I can
> leave the same function name for all types (as I would do in
> overloading). I can define a generic Bit_Set, but then I have to
> specialize it for uin16 and uint32 with different function names.

You can overload generic instances in exactly same way as you would other
subprograms:

generic
   type Data is mod <>;
   type Bit_No is range <>;
function Generic_Set_Bit (Word : Data; No : Bit_No) return Data;

function Generic_Set_Bit (Word : Data; No : Bit_No) return Data is
   pragma Assert (Data'Last = 2 ** Integer (Bit_No'Last + 1)  - 1);
begin
   return Word or 2 ** Integer (No);
end Generic_Set_Bit;

subtype Word_Index is Natural range 0..15;
function Set_Bit is
    new Generic_Set_Bit (Unsigned_16, Word_Index);

subtype Double_Word_Index is Natural range 0..31;
function Set_Bit is
    new Generic_Set_Bit (Unsigned_32, Double_Word_Index);

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: generic function and overloading
  2007-10-18  9:31 ` Dmitry A. Kazakov
@ 2007-10-18  9:33   ` Dmitry A. Kazakov
  0 siblings, 0 replies; 14+ messages in thread
From: Dmitry A. Kazakov @ 2007-10-18  9:33 UTC (permalink / raw)


BTW, types Unsigned_n are defined in the package Interfaces.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: generic function and overloading
  2007-10-18  7:28 generic function and overloading eliben
  2007-10-18  8:18 ` Jean-Pierre Rosen
  2007-10-18  9:31 ` Dmitry A. Kazakov
@ 2007-10-18 10:32 ` Georg Bauhaus
  2007-10-18 11:07 ` Stephen Leake
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: Georg Bauhaus @ 2007-10-18 10:32 UTC (permalink / raw)


eliben wrote:
> Hello,
> 
> I have a few "hardware" types, for example uint16 and uint32. And I
> want to write a functions that will set or clear bits of such types.
> For example:
> 
> function Bit_Set(word: uint16; bitn: natural) return uint16;
> 
> function Bit_Set(word: uint16; bitn: natural) return uint16 is
>   mask: uint16 := 2**bitn;
> begin
>   return word or mask;
> end Bit_Set;
> 
> However, I realize that such a function would be almost completely
> duplicated for the uint32 type. In C++ I would probably define it as a
> template on the type of the word, and the compiler would do the job
> for me.

Implicit instantiation might not be in line with the Ada
way of asking the programmers to actually say what they are doing
on behalf of readers, reviewers, and themselves.
(Otherwise use polymorphism and overriding.)

Extending J-P. Rosen's hint, you can employ visibility control
and even add a helpful prefix to the same instance name Bit_Set
instantiated in different locations (or renamed there), e.g.

    Send (Lawnmower,
       Gardening_Device_Interface.Bit_Set(Motor_Control, Silent_Mode));

Imagine a Hard_Drive_Interface if Gardening_Device_Interface
seems unreal. (It also wouldn't have to be a Lawnmower receiving
the bits, I guess, or do these things meanwhile have hard drives?)



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: generic function and overloading
  2007-10-18  7:28 generic function and overloading eliben
                   ` (2 preceding siblings ...)
  2007-10-18 10:32 ` Georg Bauhaus
@ 2007-10-18 11:07 ` Stephen Leake
  2007-10-18 11:30 ` Stefan Lucks
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: Stephen Leake @ 2007-10-18 11:07 UTC (permalink / raw)


eliben <eliben@gmail.com> writes:

> I have a few "hardware" types, for example uint16 and uint32. 

You should use Interfaces.Unsigned_16 and Unsigned_32 for these.

> And I want to write a functions that will set or clear bits of such
> types. For example:
>
> function Bit_Set(word: uint16; bitn: natural) return uint16;
>
> function Bit_Set(word: uint16; bitn: natural) return uint16 is
>   mask: uint16 := 2**bitn;
> begin
>   return word or mask;
> end Bit_Set;

Ok.

> However, I realize that such a function would be almost completely
> duplicated for the uint32 type. In C++ I would probably define it as a
> template on the type of the word, and the compiler would do the job
> for me. In Ada, however, when using generics it doesn't seem I can
> leave the same function name for all types (as I would do in
> overloading). I can define a generic Bit_Set, but then I have to
> specialize it for uin16 and uint32 with different function names. Is
> there any way I could combine the effects of generics and overloading
> and get a single Bit_Set for all my types without writing the code N
> times ?

That should work as you describe. Can you show the code that
doesn't work? Then we can help you fix it.

> P.S. Ada95

This should work in Ada 83 :). Any reason you are not in Ada 2005 yet?

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: generic function and overloading
  2007-10-18  7:28 generic function and overloading eliben
                   ` (3 preceding siblings ...)
  2007-10-18 11:07 ` Stephen Leake
@ 2007-10-18 11:30 ` Stefan Lucks
  2007-10-18 15:58 ` Robert A Duff
  2007-10-18 18:58 ` Dr. Adrian Wrigley
  6 siblings, 0 replies; 14+ messages in thread
From: Stefan Lucks @ 2007-10-18 11:30 UTC (permalink / raw)


> I have a few "hardware" types, for example uint16 and uint32. And I
> want to write a functions that will set or clear bits of such types.

> [...] I can define a generic Bit_Set, but then I have to
> specialize it for uin16 and uint32 with different function names.

I don't think so, see the example below:


--begin example
with Ada.Text_IO;

procedure X is

    generic
       type Swap_Type is private;
    procedure Gen_Swap (X,Y: in out Swap_Type);

    procedure Gen_Swap (X,Y: in out Swap_Type) is
       Tmp: Swap_Type:= X;
    begin
       X := Y;
       Y := Tmp;
    end Gen_Swap;

    type U_Int_8  is mod 2**8;
    type U_Int_16 is mod 2**16;
    type U_Int_32 is mod 2**32;

    procedure Swap is new Gen_Swap(U_Int_8);
    procedure Swap is new Gen_Swap(U_Int_16);
    procedure Swap is new Gen_Swap(U_Int_32);

    I,J: U_Int_8  := 255;
    S,T: U_Int_16 := 255;

begin
      J := J + 1;
      T := T + 1;
      Swap(I,J);
      Swap(S,T);
      if I >= J then
         Ada.Text_IO.Put_Line("Error for U_Int_8.");
      elsif S <= T then
         Ada.Text_IO.Put_Line("Error for U_Int_16.");
      else
         Ada.Text_IO.Put_Line("Everything fine, as expected!");
      end if;
end X;

-- end example

Now, if you change "Gen_Swap" into "Swap", you get an error message. 
Perhaps you got a similar error message and was puzzled by this.

So long

Stefan

-- 
Stefan Lucks      (moved to Bauhaus-University Weimar, Germany)
 		       <Stefan.Lucks at medien.uni-weimar.de>
------  I  love  the  taste  of  Cryptanalysis  in  the  morning!  ------





^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: generic function and overloading
  2007-10-18  7:28 generic function and overloading eliben
                   ` (4 preceding siblings ...)
  2007-10-18 11:30 ` Stefan Lucks
@ 2007-10-18 15:58 ` Robert A Duff
  2007-10-18 20:20   ` Simon Wright
  2007-10-18 18:58 ` Dr. Adrian Wrigley
  6 siblings, 1 reply; 14+ messages in thread
From: Robert A Duff @ 2007-10-18 15:58 UTC (permalink / raw)


eliben <eliben@gmail.com> writes:

> Hello,
>
> I have a few "hardware" types, for example uint16 and uint32. And I
> want to write a functions that will set or clear bits of such types.
> For example:
>
> function Bit_Set(word: uint16; bitn: natural) return uint16;
>
> function Bit_Set(word: uint16; bitn: natural) return uint16 is
>   mask: uint16 := 2**bitn;
> begin
>   return word or mask;
> end Bit_Set;
>
> However, I realize that such a function would be almost completely
> duplicated for the uint32 type. In C++ I would probably define it as a
> template on the type of the word, and the compiler would do the job
> for me. In Ada, however, when using generics it doesn't seem I can
> leave the same function name for all types (as I would do in
> overloading). I can define a generic Bit_Set, but then I have to
> specialize it for uin16 and uint32 with different function names. Is
> there any way I could combine the effects of generics and overloading
> and get a single Bit_Set for all my types without writing the code N
> times ?

Others answered your main question.

But do you really want to do arithmetic on these types,
as well as setting/clearing bits?  If all you want to
do is set/clear bits, you might want to consider using
a packed array of Boolean.  Then to set the Nth bit you
can say:

    X (N) := True;

Alternatively, a packed array of type Bit, where:

    type Bit is range 0..1;

If the individual bit numbers have some specific meaning,
the index type could be an enumeration type.

- Bob



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: generic function and overloading
  2007-10-18  7:28 generic function and overloading eliben
                   ` (5 preceding siblings ...)
  2007-10-18 15:58 ` Robert A Duff
@ 2007-10-18 18:58 ` Dr. Adrian Wrigley
  2007-10-18 22:30   ` Adam Beneschan
  6 siblings, 1 reply; 14+ messages in thread
From: Dr. Adrian Wrigley @ 2007-10-18 18:58 UTC (permalink / raw)


On Thu, 18 Oct 2007 00:28:38 -0700, eliben wrote:

> Hello,
> 
> I have a few "hardware" types, for example uint16 and uint32. And I
> want to write a functions that will set or clear bits of such types.
> For example:
> 
> function Bit_Set(word: uint16; bitn: natural) return uint16;
> 
> function Bit_Set(word: uint16; bitn: natural) return uint16 is
>   mask: uint16 := 2**bitn;
> begin
>   return word or mask;
> end Bit_Set;

Have you checked that packed arrays of booleans aren't
suitable?  usually you need type like this for interfacing
with other languages (eg C) - but then you use the types
in the appropriate Interfaces packages.  And you might
use such a type when writing directly to a hardware
register on a particular peripheral or bus.  But overall
its very rare that you need to write the code you're asking for!
--
Adrian




^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: generic function and overloading
  2007-10-18 15:58 ` Robert A Duff
@ 2007-10-18 20:20   ` Simon Wright
  2007-10-18 21:23     ` Robert A Duff
  0 siblings, 1 reply; 14+ messages in thread
From: Simon Wright @ 2007-10-18 20:20 UTC (permalink / raw)


Robert A Duff <bobduff@shell01.TheWorld.com> writes:

> But do you really want to do arithmetic on these types,
> as well as setting/clearing bits?  If all you want to
> do is set/clear bits, you might want to consider using
> a packed array of Boolean.  Then to set the Nth bit you
> can say:
>
>     X (N) := True;
>
> Alternatively, a packed array of type Bit, where:
>
>     type Bit is range 0..1;
>
> If the individual bit numbers have some specific meaning,
> the index type could be an enumeration type.

Will give surprising results on a big-endian machine. At least code
using shifts and masks is portable if gruesome -- and no more gruesome
than code I've written which says

   type Unrepresented is ..
   Internal : Unrepresented;
   ...

   if System.Default_Bit_Order = System.High_Order_First then
      declare
         type Represented is ..
         for Represented use ..
            -- record rep with big-endian usage
         External : constant Represented := Internal;
      begin
         Output (External);
      end;
   else
      --  equivalent for l-e



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: generic function and overloading
  2007-10-18 20:20   ` Simon Wright
@ 2007-10-18 21:23     ` Robert A Duff
  2007-10-19  5:19       ` Simon Wright
  0 siblings, 1 reply; 14+ messages in thread
From: Robert A Duff @ 2007-10-18 21:23 UTC (permalink / raw)


Simon Wright <simon.j.wright@mac.com> writes:

> Robert A Duff <bobduff@shell01.TheWorld.com> writes:
>
>> But do you really want to do arithmetic on these types,
>> as well as setting/clearing bits?  If all you want to
>> do is set/clear bits, you might want to consider using
>> a packed array of Boolean.  Then to set the Nth bit you
>> can say:
>>
>>     X (N) := True;
>>
>> Alternatively, a packed array of type Bit, where:
>>
>>     type Bit is range 0..1;
>>
>> If the individual bit numbers have some specific meaning,
>> the index type could be an enumeration type.
>
> Will give surprising results on a big-endian machine.

Only if you're doing something that exposes endianness.
Endianness should be completely invisible to most code.
(E.g., if you set the N'th bit of an array of Boolean,
and get the N'th bit, you get back what you set.
The same is true with masking modular integers.)

>... At least code
> using shifts and masks is portable if gruesome

Well, it can be portable, but you can still get into endianness
trouble if you do things like splitting the integer into
individual bytes (e.g. to transmit them across a network).

>... -- and no more gruesome
> than code I've written which says
>
>    type Unrepresented is ..
>    Internal : Unrepresented;
>    ...
>
>    if System.Default_Bit_Order = System.High_Order_First then
>       declare
>          type Represented is ..
>          for Represented use ..
>             -- record rep with big-endian usage
>          External : constant Represented := Internal;

Do you mean "type Represented is new Unrepresented;"?
Then you need a type conversion in the line above.

Nitpick: I'd use a case statement rather than an if statement, here.

>       begin
>          Output (External);
>       end;
>    else
>       --  equivalent for l-e

- Bob



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: generic function and overloading
  2007-10-18 18:58 ` Dr. Adrian Wrigley
@ 2007-10-18 22:30   ` Adam Beneschan
  0 siblings, 0 replies; 14+ messages in thread
From: Adam Beneschan @ 2007-10-18 22:30 UTC (permalink / raw)


On Oct 18, 11:58 am, "Dr. Adrian Wrigley"
<a...@linuxchip.demon.co.uk.uk.uk> wrote:
> On Thu, 18 Oct 2007 00:28:38 -0700, eliben wrote:
> > Hello,
>
> > I have a few "hardware" types, for example uint16 and uint32. And I
> > want to write a functions that will set or clear bits of such types.
> > For example:
>
> > function Bit_Set(word: uint16; bitn: natural) return uint16;
>
> > function Bit_Set(word: uint16; bitn: natural) return uint16 is
> >   mask: uint16 := 2**bitn;
> > begin
> >   return word or mask;
> > end Bit_Set;
>
> Have you checked that packed arrays of booleans aren't
> suitable?  usually you need type like this for interfacing
> with other languages (eg C) - but then you use the types
> in the appropriate Interfaces packages.  And you might
> use such a type when writing directly to a hardware
> register on a particular peripheral or bus.

Maybe that's the reason the original poster referred to them as
"hardware" types?????

                      -- Adam




^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: generic function and overloading
  2007-10-18 21:23     ` Robert A Duff
@ 2007-10-19  5:19       ` Simon Wright
  2007-10-19 13:59         ` Robert A Duff
  0 siblings, 1 reply; 14+ messages in thread
From: Simon Wright @ 2007-10-19  5:19 UTC (permalink / raw)


Robert A Duff <bobduff@shell01.TheWorld.com> writes:

> Simon Wright <simon.j.wright@mac.com> writes:
>
>> Robert A Duff <bobduff@shell01.TheWorld.com> writes:

>>> Alternatively, a packed array of type Bit, where:
>>>
>>>     type Bit is range 0..1;
>>>
>>> If the individual bit numbers have some specific meaning,
>>> the index type could be an enumeration type.
>>
>> Will give surprising results on a big-endian machine.
>
> Only if you're doing something that exposes endianness.
> Endianness should be completely invisible to most code.
> (E.g., if you set the N'th bit of an array of Boolean,
> and get the N'th bit, you get back what you set.
> The same is true with masking modular integers.)

As Adam said, this will likwly be hardware-related -- or, a near
equivalent, dealing with a C peer, possibly over a network.

>>... At least code
>> using shifts and masks is portable if gruesome
>
> Well, it can be portable, but you can still get into endianness
> trouble if you do things like splitting the integer into
> individual bytes (e.g. to transmit them across a network).

We have used GNAT's XDR-based streams on eg Interfaces.Unsigned_32 and
done the bit-twiddling afterwards (when we are reading, of course).

>>... -- and no more gruesome
>> than code I've written which says
>>
>>    type Unrepresented is ..
>>    Internal : Unrepresented;
>>    ...
>>
>>    if System.Default_Bit_Order = System.High_Order_First then
>>       declare
>>          type Represented is ..
>>          for Represented use ..
>>             -- record rep with big-endian usage
>>          External : constant Represented := Internal;
>
> Do you mean "type Represented is new Unrepresented;"?
> Then you need a type conversion in the line above.

Yes, I was writing from memory.

> Nitpick: I'd use a case statement rather than an if statement, here.

Is this for symmetry or in case some later Ada standard allows a third
option? (I could buy the symmetry/clarity argument, good point).



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: generic function and overloading
  2007-10-19  5:19       ` Simon Wright
@ 2007-10-19 13:59         ` Robert A Duff
  0 siblings, 0 replies; 14+ messages in thread
From: Robert A Duff @ 2007-10-19 13:59 UTC (permalink / raw)


Simon Wright <simon.j.wright@mac.com> writes:

> Robert A Duff <bobduff@shell01.TheWorld.com> writes:
>> Nitpick: I'd use a case statement rather than an if statement, here.
>
> Is this for symmetry or in case some later Ada standard allows a third
> option? (I could buy the symmetry/clarity argument, good point).

Symmetry/clarity.  I like case statements, because they list out all the
cases, and the compiler checks that you didn't forget any (so long as
you don't say "others"), so the reader of the code sees exactly those
cases.  And it's order independent.  With an if statement, you have
to compute in your head when "else" means.  No big deal in this case,
of course -- it's a bigger deal when there's a chain of "elsif"s.

- Bob



^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2007-10-19 13:59 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-10-18  7:28 generic function and overloading eliben
2007-10-18  8:18 ` Jean-Pierre Rosen
2007-10-18  9:31 ` Dmitry A. Kazakov
2007-10-18  9:33   ` Dmitry A. Kazakov
2007-10-18 10:32 ` Georg Bauhaus
2007-10-18 11:07 ` Stephen Leake
2007-10-18 11:30 ` Stefan Lucks
2007-10-18 15:58 ` Robert A Duff
2007-10-18 20:20   ` Simon Wright
2007-10-18 21:23     ` Robert A Duff
2007-10-19  5:19       ` Simon Wright
2007-10-19 13:59         ` Robert A Duff
2007-10-18 18:58 ` Dr. Adrian Wrigley
2007-10-18 22:30   ` Adam Beneschan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox