Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How do I create an object instance from a tag?

1 view
Skip to first unread message

Steve

unread,
Feb 17, 2003, 3:25:02 PM2/17/03
to
I would like to create a function that returns a reference to a class wide
object based on the external name. Something along the lines of:

function Create_Object( external_name : String ) return objAcc is
returnTag : Ada.Tags.Tag;
begin
returnTag := Ada.Tags.Internal_Tag( external_name );
return ??? some function of returnTag ???
end Create_Object;

Can this be done?

I've perused the rationale and the RM and haven't run across anything.

Steve
(The Duck)


Dmitry A. Kazakov

unread,
Feb 18, 2003, 3:29:04 AM2/18/03
to
On Mon, 17 Feb 2003 20:25:02 GMT, "Steve" <nospam_...@attbi.com>
wrote:

>I would like to create a function that returns a reference to a class wide
>object based on the external name. Something along the lines of:
>
>function Create_Object( external_name : String ) return objAcc is
> returnTag : Ada.Tags.Tag;
>begin
> returnTag := Ada.Tags.Internal_Tag( external_name );
> return ??? some function of returnTag ???
>end Create_Object;
>
>Can this be done?

No, you cannot dispatch on a bare tag without any object. But it seems
that this will be changed (soon?).

There could be work-arounds in specific cases. For example you could
use Ada.Streams for interesting types to define 'Input/'Output so that
no data are stored, just the tag.

---
Regards,
Dmitry Kazakov
www.dmitry-kazakov.de

Randy Brukardt

unread,
Feb 18, 2003, 1:14:39 PM2/18/03
to
Dmitry A. Kazakov wrote in message ...

>No, you cannot dispatch on a bare tag without any object. But it seems
>that this will be changed (soon?).


Well, it should be changed IMHO, but I don't think that it will be, at
least in the absense of a proposal that people like better than mine.
:-) The ways to do it that have been suggested are either not very
appealing or plain don't work.

Randy.


Steve

unread,
Feb 18, 2003, 9:27:03 PM2/18/03
to
What I "thought" was intuitive was something like:
myTag : Tags.Tag;
value : data_type'class;
for Value'Tag use myTag;

Of course that doesn't work.

Steve
(The Duck)

"Randy Brukardt" <ra...@rrsoftware.com> wrote in message
news:v54tspi...@corp.supernews.com...

Dmitry A. Kazakov

unread,
Feb 19, 2003, 4:18:56 AM2/19/03
to
On Wed, 19 Feb 2003 02:27:03 GMT, "Steve" <nospam_...@attbi.com>
wrote:

>What I "thought" was intuitive was something like:
> myTag : Tags.Tag;
> value : data_type'class;
> for Value'Tag use myTag;
>
>Of course that doesn't work.

IMO, the following is more consistent:

myTag : Tags.Tag := ...;
value : data_type'class (myTag);

and for dispatching:

myTag : Tags.Tag := ...;
value : data_type'class (myTag) := Create_Value;

or fully dynamically (qualified expression):

myTag : Tags.Tag := ...;
value : data_type'class :=
data_type'class (myTag)'(Create_Value);

Grein, Christoph

unread,
Feb 19, 2003, 4:39:56 AM2/19/03
to comp.l...@ada.eu.org
Problem with this proposal is abstract types. There must not be objects of an
abstract type.

So if myTag denotes an abstract type, the proposal is illegal. It should at
least propagate Program_Error.

So there are good reasons why there is not yet a solution for this problem.

(A solution, together with some trivial other amendments, could be used to find
the nearest common ancestor of two tagged objects. Currently there is no way to
find it.)

Dmitry A. Kazakov

unread,
Feb 19, 2003, 8:26:36 AM2/19/03
to
On Wed, 19 Feb 2003 10:39:56 +0100 (MET), "Grein, Christoph"
<christo...@eurocopter.com> wrote:

>Problem with this proposal is abstract types. There must not be objects of an
>abstract type.
>
>So if myTag denotes an abstract type, the proposal is illegal. It should at
>least propagate Program_Error.

Constraint_Error, I would say. It is statically uncheckable. BTW, the
source of the problem with it is that S'Tag "leaks". IMO there is no
much sense in having tags of imaginary objects. So S'Tag could raise
an exception if S is abstract (or unconstrained?).

>So there are good reasons why there is not yet a solution for this problem.

Similar problem exists with S'Class'Input, if you mangle stream data
so that an abstract type tag appears there.

>(A solution, together with some trivial other amendments, could be used to find
>the nearest common ancestor of two tagged objects. Currently there is no way to
>find it.)

I do not see it as the same problem. Are there many cases where the
above could be useful? Sort of MD for poor? (:-))

Tag comparisons (>, >=, <, <=) could be indeed useful.

Randy Brukardt

unread,
Feb 19, 2003, 1:36:25 PM2/19/03
to
"Grein, Christoph"<christo...@eurocopter.com> wrote:
>
>So there are good reasons why there is not yet a solution for this
problem.


The main one is discriminants. Tagged type discriminants never have
defaults. Moreover, you can add discriminants to any extension of a
tagged type, so you never can know if you have any. And, certainly, the
creation of an object with uninitialized discriminants is a no-no.

What you really want to do is force the calling of a particular
constructor function. (That's what T'Class'Input does, after all, with
T'Input being the constructor).

If you have a dispatching constructor "Make", then you want something
like:

Obj : T'Class := T.Make (<params>) using <tag object>;

But the reviewers thought that special syntax was overkill for this
problem, and no one has been able to come up with any other solution
that really works.

Randy.


Dmitry A. Kazakov

unread,
Feb 20, 2003, 4:15:53 AM2/20/03
to
On Wed, 19 Feb 2003 12:36:25 -0600, "Randy Brukardt"
<ra...@rrsoftware.com> wrote:

>"Grein, Christoph"<christo...@eurocopter.com> wrote:
>>
>>So there are good reasons why there is not yet a solution for this
>problem.
>
>The main one is discriminants. Tagged type discriminants never have
>defaults. Moreover, you can add discriminants to any extension of a
>tagged type, so you never can know if you have any. And, certainly, the
>creation of an object with uninitialized discriminants is a no-no.

[ I think we have already discussed this. A full solution is IMO only
possible with proper constructors. ]

As for uninialized discriminants, compare:

type X (I : Positive) is record ...;

A : X; -- Illegal
B : X := (I => 10, ...); -- OK

How does it differ from:

A : X'Class (A_Tag);
-- Raises an exception when A_Tag refers to an unconstrained type
A : X'Class (A_Tag) := Make_X;
-- Dispatches to Make_X, which provides all constraints

The only diference is that the latter is not compile-time checkable.

However this can be solved. For example, one could define two
different tag types: one for all types another for constrained types
only [with appropriate conversion functions between them]. Then with a
general tag, T'Class(Tag) would counted as unconstrained, and thus
illegal without an initialization. With a "constrained" tag
T'Class(Tag) would be OK.

>What you really want to do is force the calling of a particular
>constructor function. (That's what T'Class'Input does, after all, with
>T'Input being the constructor).
>
>If you have a dispatching constructor "Make", then you want something
>like:
>
> Obj : T'Class := T.Make (<params>) using <tag object>;
>
>But the reviewers thought that special syntax was overkill for this
>problem, and no one has been able to come up with any other solution
>that really works.

Special syntax is bad here, because there is nothing special in
dispatching on the result. There is everything for that. IMO the
actual problem is an unability to specifiy the type of the target
object. Solve this, and the rest will come for free. IMHO tag should
be viewed as a constraint (discriminant) for T'Class.

Julio Cano

unread,
Feb 20, 2003, 10:38:21 AM2/20/03
to
"Steve" <nospam_...@attbi.com> wrote in message news:<yyb4a.155282$vm2.110486@rwcrnsc54>...

> I would like to create a function that returns a reference to a class wide
> object based on the external name. Something along the lines of:
>
> function Create_Object( external_name : String ) return objAcc is
> returnTag : Ada.Tags.Tag;
> begin
> returnTag := Ada.Tags.Internal_Tag( external_name );
> return ??? some function of returnTag ???
> end Create_Object;
>
> Can this be done?
>

It depends on what you actually want. You can have "some function of
returnTag" if you have already registered the tagged type constructor
with its tag.
You can do this with a tagged type hierarchy. Just define the
constructor like this:
function create return obj_class_acc
being
type obj_class_acc is access obj'class

Defining all subtypes constructors like this:
function create return obj_class_acc is
begin
return new derived_obj'class;
end;
Note return type is obj_class_acc (base type).

Now you can "register" all the constructors in a package:
type constr_func is access function return obj_class_acc;
procedure register_constructor (type_name: string;
constructor: constr_func);

and look for the constructor like this:
function objectforname(type_name: string) return constr_func;

Register somewhere (i.e: in the package of the type)
register_constructor("this_class_name", constructor'access);

And create object based in its name:
my_obj : obj_class_acc := objectforname("this_class_name").all;
do_something(my_obj.all);

This solution is obviously restricted to a hierarchy, and
obj_class_acc most be the base type.
I think that one of the problems here is the lack of a generic base
type like (Object in Java, Id in Objective-C, ...). That kind of base
type or generic access type would help to implement a more generic
(and may be more dangerous) solution.

0 new messages