comp.lang.ada
 help / color / mirror / Atom feed
* How to get generic formal parameter type into base class
@ 2012-10-05 22:23 kevin.miscellaneous
  2012-10-05 23:38 ` Georg Bauhaus
  2012-10-06  3:28 ` Adam Beneschan
  0 siblings, 2 replies; 9+ messages in thread
From: kevin.miscellaneous @ 2012-10-05 22:23 UTC (permalink / raw)


Is there a way to get a generic formal parameter type into base class so that I can dispatch to a function with that type in the function signature? Below is what I am trying to achieve, and of course the main procedure will not compile.
Thanks,

package Classes is

   type Value_Type is range -2 ** 31 .. 2 ** 31 - 1;

   generic
      type Data_Type is (<>);
   package Translate_Base is

      type Xlate_Base_Type is abstract tagged record
         Value : Data_Type := Data_Type'first;
      end record;

      procedure Decode   (Xlate_Class : in out Xlate_Base_Type; 
                          Value : in Value_Type) is abstract;
      function  Encode   (Xlate_Class : in     Xlate_Base_Type) 
                          return Value_Type is abstract;
      function  Get_Value(Xlate_Class : in     Xlate_Base_Type) 
                          return Data_Type is abstract;
      procedure Set_Value(Xlate_Class : in out Xlate_Base_Type; 
                          Value : in Data_Type) is abstract;

   end Translate_Base;


   generic
      type Data_Type is (<>);
   package Translate_Integer is

      package base is new Translate_Base(Data_Type);
      type Xlate_Type is new base.Xlate_Base_Type with record
         Signed     : Boolean   := False;
      end record;

      procedure Decode   (Xlate_Class : in out Xlate_Type; 
                          Value : in Value_Type);
      function  Encode   (Xlate_Class : in     Xlate_Type) return Value_Type;
      function  Get_Value(Xlate_Class : in     Xlate_Type) return Data_Type;
      procedure Set_Value(Xlate_Class : in out Xlate_Type; 
                          Value : in Data_Type);

   end Translate_Integer;

   -- define Translate_Enumuration
   -- define Translate_Float
   -- ...

end Classes;


package body Classes is

   package body Translate_Integer is


      procedure Decode   (Xlate_Class : in out Xlate_Type; 
                          Value : in Value_Type) is
      begin
         Xlate_Class.Value := Data_Type'val(Value);
      end Decode;


      function  Encode   (Xlate_Class : in     Xlate_Type) return Value_Type is
      begin
         return Data_Type'pos(Xlate_Class.Value);
      end Encode;


      function  Get_Value(Xlate_Class : in     Xlate_Type) return Data_Type is
      begin
         return Xlate_Class.Value;
      end Get_Value;


      procedure Set_Value(Xlate_Class : in out Xlate_Type; 
                          Value : in Data_Type) is
      begin
          Xlate_Class.Value := Value;
      end Set_Value;

   end Translate_Integer;

end Classes;


with Classes;

package Objects is

   type Int_100_Type is range -100 .. 100;

   package Int_100 is new Classes.Translate_Integer(Int_100_Type);

end Objects;


with Classes;
with Objects;
with Ada.Text_IO;


procedure main is

   procedure PrintLn(Item : String) renames Ada.Text_IO.Put_Line;

   type Message_ID_Type is (type1);

   function Factory_Get (Message_ID : in Message_ID_Type) 
                         return Classes.Xlate_Base_Type'class is
   begin

      case Message_ID is
      when type1 =>
         declare
            This : Objects.Int_100.Xlate_Type;
         begin
            return This;
         end;
      end case;

   end Factory_Get;


   This : Classes.Xlate_Base_Type'class := Factory_Get(type1);
   Value : Classes.Value_Type;
   My_Value : Objects.Int_100_Type;
begin

   Value := 255;  -- get FF from input stream.
   Classes.Translate_Base.Decode(This, Value);
   My_Value := Classes.Translate_Base.Get_Value(This);

   -- do something

   Classes.Translate_Base.Set_Value(This, My_Value);
   Value := Classes.Translate_Base.Encode(This);
end main;
 



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

* Re: How to get generic formal parameter type into base class
  2012-10-05 22:23 How to get generic formal parameter type into base class kevin.miscellaneous
@ 2012-10-05 23:38 ` Georg Bauhaus
  2012-10-06  3:28 ` Adam Beneschan
  1 sibling, 0 replies; 9+ messages in thread
From: Georg Bauhaus @ 2012-10-05 23:38 UTC (permalink / raw)


On 06.10.12 00:23, kevin.miscellaneous@gmail.com wrote:
> This : Classes.Xlate_Base_Type'class := Factory_Get(type1);


Xlate_Base_Type is defined inside generic package
Classes.Translate_Base. Only instances Xyz of this template
allow referring to Xyz.Xlate_Base_Type['Class] elsewhere.
Like in base.Xlate_Base_Type. Classes.Xlate_Base_Type does
not exist at all, and in Classes.Translate_Base.*
"Classes.Translate_Base" is not a valid prefix for that
reason.

Just guessing, it might be helpful to _not_ associate generic
Ada packages with C++ class templates; generic packages are
as if C++ had generic _namespaces_.




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

* Re: How to get generic formal parameter type into base class
  2012-10-05 22:23 How to get generic formal parameter type into base class kevin.miscellaneous
  2012-10-05 23:38 ` Georg Bauhaus
@ 2012-10-06  3:28 ` Adam Beneschan
  2012-10-06 20:03   ` kevin andrew
  1 sibling, 1 reply; 9+ messages in thread
From: Adam Beneschan @ 2012-10-06  3:28 UTC (permalink / raw)


On Friday, October 5, 2012 3:23:01 PM UTC-7, (unknown) wrote:
> Is there a way to get a generic formal parameter type into base class so that I can dispatch to a function with that type in the function signature? Below is what I am trying to achieve, and of course the main procedure will not compile.
> 
> Thanks,
> 
> 
> 
> package Classes is
> 
>    type Value_Type is range -2 ** 31 .. 2 ** 31 - 1;
> 
>    generic
>       type Data_Type is (<>);
>    package Translate_Base is
> 
>       type Xlate_Base_Type is abstract tagged record
>          Value : Data_Type := Data_Type'first;
>       end record; 
> 
>       procedure Decode   (Xlate_Class : in out Xlate_Base_Type; 
>                           Value : in Value_Type) is abstract;
>       function  Encode   (Xlate_Class : in     Xlate_Base_Type) 
>                           return Value_Type is abstract;
>       function  Get_Value(Xlate_Class : in     Xlate_Base_Type) 
>                           return Data_Type is abstract;
>       procedure Set_Value(Xlate_Class : in out Xlate_Base_Type; 
>                           Value : in Data_Type) is abstract;
>
>    end Translate_Base;
> 
> 
>    generic
>       type Data_Type is (<>);
>    package Translate_Integer is 
> 
>       package base is new Translate_Base(Data_Type);
>       type Xlate_Type is new base.Xlate_Base_Type with record
>          Signed     : Boolean   := False;
>       end record;
> 
>       procedure Decode   (Xlate_Class : in out Xlate_Type; 
>                           Value : in Value_Type);
>       function  Encode   (Xlate_Class : in     Xlate_Type) return Value_Type;
>       function  Get_Value(Xlate_Class : in     Xlate_Type) return Data_Type;
>       procedure Set_Value(Xlate_Class : in out Xlate_Type; 
>                           Value : in Data_Type);
> 
>    end Translate_Integer;
> 
>    -- define Translate_Enumuration
>    -- define Translate_Float
>    -- ...
> 
> end Classes;
> 
> package body Classes is
> 
>    package body Translate_Integer is
> 
>       procedure Decode   (Xlate_Class : in out Xlate_Type; 
>                           Value : in Value_Type) is
>       begin
>          Xlate_Class.Value := Data_Type'val(Value);
>       end Decode;
> 
>       function  Encode   (Xlate_Class : in     Xlate_Type) return Value_Type is
>       begin
>          return Data_Type'pos(Xlate_Class.Value);
>       end Encode;
> 
>       function  Get_Value(Xlate_Class : in     Xlate_Type) return Data_Type is
>       begin
>          return Xlate_Class.Value;
>       end Get_Value;
> 
>       procedure Set_Value(Xlate_Class : in out Xlate_Type; 
>                           Value : in Data_Type) is
>       begin
>           Xlate_Class.Value := Value;
>       end Set_Value;
>    end Translate_Integer;
> 
> end Classes;
> 
> with Classes;
> 
> package Objects is
> 
>    type Int_100_Type is range -100 .. 100;
> 
>    package Int_100 is new Classes.Translate_Integer(Int_100_Type);
> 
> end Objects; 
> 
> with Classes;
> with Objects;
> with Ada.Text_IO;
> 
> procedure main is

>    procedure PrintLn(Item : String) renames Ada.Text_IO.Put_Line;
> 
>    type Message_ID_Type is (type1);
> 
>    function Factory_Get (Message_ID : in Message_ID_Type)  
>                          return Classes.Xlate_Base_Type'class is
>    begin
>
>       case Message_ID is
>       when type1 =>
>          declare
>             This : Objects.Int_100.Xlate_Type;
>          begin
>             return This;
>          end;
>       end case;
> 
>    end Factory_Get;
> 
>    This : Classes.Xlate_Base_Type'class := Factory_Get(type1);
>    Value : Classes.Value_Type;
>    My_Value : Objects.Int_100_Type;
> begin
> 
>    Value := 255;  -- get FF from input stream.
>    Classes.Translate_Base.Decode(This, Value);
>    My_Value := Classes.Translate_Base.Get_Value(This);
> 
>    -- do something
> 
>    Classes.Translate_Base.Set_Value(This, My_Value);
>    Value := Classes.Translate_Base.Encode(This);
> end main;

Since you're trying to use Xlate_Type'Class, it looks like you're thinking that the types involved are all related.  They're not.  A generic package isn't useful until you instantiate it, and instantiating the package has pretty much the same effect as writing it all over again, substituting something different for the formal parameters.  It's something like a macro substitution.  And if you had two types with the same name in different packages, e.g.

   package Instantiation_1 is
      type Xlate_Type is tagged record ...
   end Instantiation_1;

   package Instantiation_2 is
      type Xlate_Type is tagged record ...
   end Instantiation_2;

you wouldn't expect the two Xlate_Type types to be related at all, and you wouldn't expect a 'Class type to be able to represent both.  Well, that's pretty much what you're getting when you define the type in the instantiation.

What I think you want to do is declare an abstract root type *outside* any generic, and declare abstract procedures/functions Decode, Encode, etc., in the same package outside the generic.  Then, in Translate_Base (which could still be generic), make your Xlate_Type a type extension of that root type.  Now you can declare something as Your_Root_Type'Class and this object could represent any type derived from Your_Root_Type, including those in generic instantiations, and it could dispatch to those procedures and functions.

Hope this helps,

                               -- Adam



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

* Re: How to get generic formal parameter type into base class
  2012-10-06  3:28 ` Adam Beneschan
@ 2012-10-06 20:03   ` kevin andrew
  2012-10-07  3:06     ` Adam Beneschan
  2012-10-07  7:42     ` Dmitry A. Kazakov
  0 siblings, 2 replies; 9+ messages in thread
From: kevin andrew @ 2012-10-06 20:03 UTC (permalink / raw)


On Oct 5, 8:28 pm, Adam Beneschan <a...@irvine.com> wrote:
> On Friday, October 5, 2012 3:23:01 PM UTC-7, (unknown) wrote:
> > Is there a way to get a generic formal parameter type into base class so that I can dispatch to a function with that type in the function signature? Below is what I am trying to achieve, and of course the main procedure will not compile.
>
> > Thanks,
>
> > package Classes is
>
> >    type Value_Type is range -2 ** 31 .. 2 ** 31 - 1;
>
> >    generic
> >       type Data_Type is (<>);
> >    package Translate_Base is
>
> >       type Xlate_Base_Type is abstract tagged record
> >          Value : Data_Type := Data_Type'first;
> >       end record;
>
> >       procedure Decode   (Xlate_Class : in out Xlate_Base_Type;
> >                           Value : in Value_Type) is abstract;
> >       function  Encode   (Xlate_Class : in     Xlate_Base_Type)
> >                           return Value_Type is abstract;
> >       function  Get_Value(Xlate_Class : in     Xlate_Base_Type)
> >                           return Data_Type is abstract;
> >       procedure Set_Value(Xlate_Class : in out Xlate_Base_Type;
> >                           Value : in Data_Type) is abstract;
>
> >    end Translate_Base;
>
> >    generic
> >       type Data_Type is (<>);
> >    package Translate_Integer is
>
> >       package base is new Translate_Base(Data_Type);
> >       type Xlate_Type is new base.Xlate_Base_Type with record
> >          Signed     : Boolean   := False;
> >       end record;
>
> >       procedure Decode   (Xlate_Class : in out Xlate_Type;
> >                           Value : in Value_Type);
> >       function  Encode   (Xlate_Class : in     Xlate_Type) return Value_Type;
> >       function  Get_Value(Xlate_Class : in     Xlate_Type) return Data_Type;
> >       procedure Set_Value(Xlate_Class : in out Xlate_Type;
> >                           Value : in Data_Type);
>
> >    end Translate_Integer;
>
> >    -- define Translate_Enumuration
> >    -- define Translate_Float
> >    -- ...
>
> > end Classes;
>
> > package body Classes is
>
> >    package body Translate_Integer is
>
> >       procedure Decode   (Xlate_Class : in out Xlate_Type;
> >                           Value : in Value_Type) is
> >       begin
> >          Xlate_Class.Value := Data_Type'val(Value);
> >       end Decode;
>
> >       function  Encode   (Xlate_Class : in     Xlate_Type) return Value_Type is
> >       begin
> >          return Data_Type'pos(Xlate_Class.Value);
> >       end Encode;
>
> >       function  Get_Value(Xlate_Class : in     Xlate_Type) return Data_Type is
> >       begin
> >          return Xlate_Class.Value;
> >       end Get_Value;
>
> >       procedure Set_Value(Xlate_Class : in out Xlate_Type;
> >                           Value : in Data_Type) is
> >       begin
> >           Xlate_Class.Value := Value;
> >       end Set_Value;
> >    end Translate_Integer;
>
> > end Classes;
>
> > with Classes;
>
> > package Objects is
>
> >    type Int_100_Type is range -100 .. 100;
>
> >    package Int_100 is new Classes.Translate_Integer(Int_100_Type);
>
> > end Objects;
>
> > with Classes;
> > with Objects;
> > with Ada.Text_IO;
>
> > procedure main is
> >    procedure PrintLn(Item : String) renames Ada.Text_IO.Put_Line;
>
> >    type Message_ID_Type is (type1);
>
> >    function Factory_Get (Message_ID : in Message_ID_Type)
> >                          return Classes.Xlate_Base_Type'class is
> >    begin
>
> >       case Message_ID is
> >       when type1 =>
> >          declare
> >             This : Objects.Int_100.Xlate_Type;
> >          begin
> >             return This;
> >          end;
> >       end case;
>
> >    end Factory_Get;
>
> >    This : Classes.Xlate_Base_Type'class := Factory_Get(type1);
> >    Value : Classes.Value_Type;
> >    My_Value : Objects.Int_100_Type;
> > begin
>
> >    Value := 255;  -- get FF from input stream.
> >    Classes.Translate_Base.Decode(This, Value);
> >    My_Value := Classes.Translate_Base.Get_Value(This);
>
> >    -- do something
>
> >    Classes.Translate_Base.Set_Value(This, My_Value);
> >    Value := Classes.Translate_Base.Encode(This);
> > end main;
>
> Since you're trying to use Xlate_Type'Class, it looks like you're thinking that the types involved are all related.  They're not.  A generic package isn't useful until you instantiate it, and instantiating the package has pretty much the same effect as writing it all over again, substituting something different for the formal parameters.  It's something like a macro substitution.  And if you had two types with the same name in different packages, e.g.
>
>    package Instantiation_1 is
>       type Xlate_Type is tagged record ...
>    end Instantiation_1;
>
>    package Instantiation_2 is
>       type Xlate_Type is tagged record ...
>    end Instantiation_2;
>
> you wouldn't expect the two Xlate_Type types to be related at all, and you wouldn't expect a 'Class type to be able to represent both.  Well, that's pretty much what you're getting when you define the type in the instantiation.
>
> What I think you want to do is declare an abstract root type *outside* any generic, and declare abstract procedures/functions Decode, Encode, etc., in the same package outside the generic.  Then, in Translate_Base (which could still be generic), make your Xlate_Type a type extension of that root type.  Now you can declare something as Your_Root_Type'Class and this object could represent any type derived from Your_Root_Type, including those in generic instantiations, and it could dispatch to those procedures and functions.
>
> Hope this helps,
>
>                                -- Adam- Hide quoted text -
>
> - Show quoted text -


Thanks for the responses.

I still don't see how to get a dynamic type into base class so that I
can dispatch to a function with that type in the function signature.
If I do a Root_Type then I don't see how I can include the Get/
Set_Value function because Data_Type is unknown? Any help getting my
ignorant mine understanding Ada will be greatly appreciated.  I have
included a better Main procedure which more accurately shows what I am
trying to do.

Thanks,
Kevin.

with Classes;

package Objects is

   type Mod_12_Type is mod 2 ** 12;
   type Int_100_Type is range -100 .. 100;
   type Enum_One_Type is (Minus_0ne, Zero, One);

   type External_Type is record
      theMode : Mod_12_Type;
      theInt  : Int_100_Type;
      theEnum : Enum_One_Type;
   end record;

   package Mod_12   is new Classes.Translate_Integer(Mod_12_Type);
   package Int_100  is new Classes.Translate_Integer(Int_100_Type);
   package Enum_One is new Classes.Translate_Integer(Enum_One_Type);

end Objects;



with Classes;
with Objects;
with Ada.Text_IO;


procedure main is

   procedure PrintLn(Item : String) renames Ada.Text_IO.Put_Line;

   type Message_ID_Type is (Int_100, Mod_12, Enum_One);

   function Factory_Get (Message_ID : in Message_ID_Type) return
Classes.Xlate_Base_Type'class is
   begin

      case Message_ID is

      when Int_100 =>
         declare
            This : Objects.Int_100.Xlate_Type;
         begin
            return This;
         end;

      when Mod_12 =>
         declare
            This : Objects.Mod_12.Xlate_Type;
         begin
            return This;
         end;

      when Enum_One =>
         declare
            This : Objects.Enum_One.Xlate_Type;
         begin
            return This;
         end;
      end case;

   end Factory_Get;


   Procedure Get_Values(Message_ID : in Message_ID_Type;
                        Class      : in Classes.Xlate_Base_Type'class;
                        Msg        : in out Objects.External_Type) is
   begin
      case Message_ID is

      when Int_100 =>
         Msg.theInt := Classes.Translate_Base.Get_Value(Class); --
Dispatch to Get_Value

      when Mod_12 =>
         Msg.theMode := Classes.Translate_Base.Get_Value(Class); --
Dispatch to Get_Value

      when Enum_One =>
         Msg.theEnum := Classes.Translate_Base.Get_Value(Class); --
Dispatch to Get_Value

      end case;
   end Get_Values;

   procedure Decode(Message_ID : in Message_ID_Type;
                    Value : in Classes.Value_Type;
                    Msg        : in out Objects.External_Type) is
      This : Classes.Xlate_Base_Type'class := Factory_Get(Message_ID);
   begin
      Classes.Translate_Base.Decode(This, Value);  -- Dispatch to
Decode
      Get_Values(Message_ID, This, Msg);
   end Decode;

   Value : Classes.Value_Type;
   Message  : Objects.External_Type;
begin

   Value := 255;  -- get FF from input stream.
   Decode(Int_100, Value, Message);

   Value := 240;  -- get F0 from input stream.
   Decode(Mod_12, Value, Message);

   Value := 0;  -- get 00 from input stream.
   Decode(Enum_One, Value, Message);

   -- print Message.

end main;



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

* Re: How to get generic formal parameter type into base class
  2012-10-06 20:03   ` kevin andrew
@ 2012-10-07  3:06     ` Adam Beneschan
  2012-10-11 20:25       ` kevin andrew
  2012-10-07  7:42     ` Dmitry A. Kazakov
  1 sibling, 1 reply; 9+ messages in thread
From: Adam Beneschan @ 2012-10-07  3:06 UTC (permalink / raw)


On Saturday, October 6, 2012 1:03:34 PM UTC-7, kevin andrew wrote:

> I still don't see how to get a dynamic type into base class so that I
> can dispatch to a function with that type in the function signature.
> If I do a Root_Type then I don't see how I can include the Get/
> Set_Value function because Data_Type is unknown? 

Right.  It was a bit late when I posted my response, so I didn't notice that Get/Set_Value would involve different result/parameter types so it couldn't be defined for the root type.  But if the procedure involves different result/parameter types, you can't really **dispatch** to it, can you?  For dispatching to work (and I think this applies to C++ and other OO languages as well), the types of everything except your Xlate_Type or Xlate_Base_Type have to be known; then the program decides at runtime which is the correct procedure or function to call.

In your case, I think what you want is this: Define Encode and Decode for your root type, but not Get_Value or Set_Value.  Go ahead and define Get_Value and Set_Value in the generic, but note that each instantiation of the generic will produce a different, and unrelated, declaration of Get_Value or Set_Value.  Since they're unrelated, you can't use a dispatching call to call them.  But your code wasn't trying to do that.  (In essence, you were using your own CASE statement to do a fake "dispatch".)  So when you wrote:

>       when Int_100 =>
>          Msg.theInt := Classes.Translate_Base.Get_Value(Class); --

if Class is declared with type Your_Root_Type'Class, you'll need to convert it to the specific type, and call the function declared in the specific generic instance:

         when Int_100 =>
           Msg.theInt := Objects.Int_100.Get_Value 
                           (Objects.Int_100.Xlate_Type(Class));

or, more simply:

         when Int_100 =>
           Msg.theInt := Objects.Int_100.Xlate_Type(Class).Get_Value;

Objects.Int_100.Xlate_Type(Class) is a kind of "type conversion" that tells the compiler that Class, which is declared as Your_Root_Type'Class, actually has the type Objects.Int_100.Xlate_Type (and it will check at run time that this is true, and raise an exception if not).

Please note, I'm at home and don't have easy access to an Ada compiler, so I can't try this myself to make sure it works.

Hope this helps,

                            -- Adam



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

* Re: How to get generic formal parameter type into base class
  2012-10-06 20:03   ` kevin andrew
  2012-10-07  3:06     ` Adam Beneschan
@ 2012-10-07  7:42     ` Dmitry A. Kazakov
  1 sibling, 0 replies; 9+ messages in thread
From: Dmitry A. Kazakov @ 2012-10-07  7:42 UTC (permalink / raw)


On Sat, 6 Oct 2012 13:03:34 -0700 (PDT), kevin andrew wrote:

> I still don't see how to get a dynamic type into base class so that I
> can dispatch to a function with that type in the function signature.
> If I do a Root_Type then I don't see how I can include the Get/
> Set_Value function because Data_Type is unknown? Any help getting my
> ignorant mine understanding Ada will be greatly appreciated.  I have
> included a better Main procedure which more accurately shows what I am
> trying to do.

[...]

Why do you need Get_Values? If there will be a specific descendant type of
Xate_Base_Type for each scalar value type, that will have a Get_Value of
its own. And in any case, passing type ID to Get_Values does not make much
sense because the instance of Xate_Base_Type already "knows" its scalar
counterpart.

Since scalar types do not belong to the same hierarchy of types, not
tagged, and full double dispatch is not supported anyway, adding Decode on
top of Get_Values does not change anything. You still need to pass a
specific type of the Value into it.

So either you have a distinct operation per scalar type defined at the root
or you use some container type capable to hold instances of them. E.g. a
stream, a variant record type etc.

P.S. You don't need generics for this case unless you have many different
scalar types of same origin to support, e.g. integer types of various
sizes.

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



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

* Re: How to get generic formal parameter type into base class
  2012-10-07  3:06     ` Adam Beneschan
@ 2012-10-11 20:25       ` kevin andrew
  2012-10-11 23:28         ` Georg Bauhaus
  2012-10-11 23:52         ` Georg Bauhaus
  0 siblings, 2 replies; 9+ messages in thread
From: kevin andrew @ 2012-10-11 20:25 UTC (permalink / raw)



Thanks Adam,
Your solution is the workaround I had used. Ada is so strongly type
cast I didn't think I would be able to do what I wanted.
FYI, you can do this with C++ template classes, and though I have
never tried, Java has added templates as well.
C solution:

#include <iostream>
using namespace std;

typedef int value_t;


template <typename T>
class baseClass
{
public:
   baseClass( ) {  }

   void decode  ( value_t value ) { }
   T    getValue( void ) { }

protected:
   T data;
   value_t value;

private:

};

template <typename T>
class newClass : public baseClass<T>
{

public:
   newClass()  { }
   void decode  ( value_t value )
   {
      this->value = value;
      this->data = (T)value;
   }
   T  getValue( void )
   {
      return this->data;
   }

private:

};


int main()
{
   newClass<int> intClass;
   newClass<char> charClass;

   value_t value = 4;
   intClass.decode(value);
   int i = intClass.getValue();

   value = 97;
   charClass.decode(value);
   char ch = charClass.getValue();

   cout << "int=" << i << "  ch=" << ch  << endl;

}



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

* Re: How to get generic formal parameter type into base class
  2012-10-11 20:25       ` kevin andrew
@ 2012-10-11 23:28         ` Georg Bauhaus
  2012-10-11 23:52         ` Georg Bauhaus
  1 sibling, 0 replies; 9+ messages in thread
From: Georg Bauhaus @ 2012-10-11 23:28 UTC (permalink / raw)


On 11.10.12 22:25, kevin andrew wrote:
>
> Thanks Adam,
> Your solution is the workaround I had used. Ada is so strongly type
> cast I didn't think I would be able to do what I wanted.
> FYI, you can do this with C++ template classes,

You can't, really. It hinges on char and int matching. Try this:

struct T {};

int main()
{
    newClass<int> intClass;
    newClass<T> charClass;
  ...
}





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

* Re: How to get generic formal parameter type into base class
  2012-10-11 20:25       ` kevin andrew
  2012-10-11 23:28         ` Georg Bauhaus
@ 2012-10-11 23:52         ` Georg Bauhaus
  1 sibling, 0 replies; 9+ messages in thread
From: Georg Bauhaus @ 2012-10-11 23:52 UTC (permalink / raw)


On 11.10.12 22:25, kevin andrew wrote:

> FYI, you can do this with C++ template classes, and though I have
> never tried, Java has added templates as well.

Like the C++ version, this establishes the required
relationship between Int and Char; C++'s protected
visibility is achieved with the help of a child package.

package Typedef is
    
    subtype Value_T is Integer;
    
end Typedef;

with Typedef; use Typedef;

generic
    type T is new Value_T;
package BaseClass is
    
    type BaseClass is tagged private;
    procedure Decode (Item : in out BaseClass; Value: Value_T) is null;
    function GetValue (Item : BaseClass) return T;
private
    type BaseClass is tagged record
       Data : T;
       Value : Value_T;
    end record;
end BaseClass;

package body Baseclass is
    Default : T;
    function GetValue (Item : BaseClass) return T is
    begin
       return Default;
    end GetValue;
    
end Baseclass;

with Typedef; use Typedef;
generic
    type T is new Value_T;
package BaseClass.NewClass is
    type NewClass is new BaseClass with private;
    overriding procedure Decode (Item : in out NewClass; Value: Value_T);
    overriding function GetValue (Item : NewClass) return Standard.BaseClass.T;
private
    type NewClass is new BaseClass with null record;
end BaseClass.NewClass;

package body BaseClass.NewClass is
    overriding procedure Decode (Item : in out NewClass; Value: Value_T) is
    begin
       Item.Value := Value;
       Item.Data := STandard.BaseClass.T(Value);
    end Decode;
    
    overriding function GetValue (Item : NewClass) return Standard.BaseClass.T is
    begin
       return Item.Data;
    end Getvalue;
end BaseClass.NewClass;

    
with Typedef; use Typedef;
with BaseClass.NewClass;
with Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure main is
    
    subtype Int is Integer range Integer'Range;
    subtype Char is Integer range -128 .. 127;
    
    package BaseClassInstance is new BaseClass(Int);
    package NewClassInt is new BaseClassInstance.NewClass(Int);
    IntClass: NewClassInt.NewClass;
    
    package BaseClassInstance2 is new BaseClass(Char);
    package NewClassChar is new BaseClassInstance2.NewClass(Char);
    CharClass: NewClassChar.NewClass;
    
    Value : Value_T := 4;
begin
    IntClass.Decode(Value);
    declare
       I : Integer := IntClass.GetValue;
    begin
       Value := 97;
       CharClass.Decode(Value);
       declare
          Ch: Char := CharClass.GetValue;
          use Ada.Text_IO, Ada.Integer_Text_IO;
       begin
          Default_Width := 0;
          Put ("int="); Put(I); Put("  ch="); Put (Character'Val(Ch)); New_Line;
       end;
    end;
end Main;





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

end of thread, other threads:[~2012-10-16  1:56 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-10-05 22:23 How to get generic formal parameter type into base class kevin.miscellaneous
2012-10-05 23:38 ` Georg Bauhaus
2012-10-06  3:28 ` Adam Beneschan
2012-10-06 20:03   ` kevin andrew
2012-10-07  3:06     ` Adam Beneschan
2012-10-11 20:25       ` kevin andrew
2012-10-11 23:28         ` Georg Bauhaus
2012-10-11 23:52         ` Georg Bauhaus
2012-10-07  7:42     ` Dmitry A. Kazakov

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