comp.lang.ada
 help / color / mirror / Atom feed
* Specialization
@ 2002-05-30 12:39 Baugereau
  2002-05-30 17:09 ` Specialization Ted Dennison
  2002-05-30 17:46 ` Specialization Toshitaka Kumano
  0 siblings, 2 replies; 22+ messages in thread
From: Baugereau @ 2002-05-30 12:39 UTC (permalink / raw)


Hello,

I'm trying to implement a generic container, say a extensible vector.
But I'd like to specialize this component for controlled types.
For instance, when I empty the container, I want to Finalize all the
elements if they are Controlled, and do nothing if not.
Of course, I want to keep the same syntax in client code.
Is there a way, like in C++ (I come from a C++ background, maybe my view is
too much "C++ template"-biased), to specialize the procedures of the package
for some flavours of the generic parameter?
I tried to check the ARM but I'm not fluent enough in Ada I guess...

Thanks,
Bertrand






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

* Re: Specialization
  2002-05-30 12:39 Specialization Baugereau
@ 2002-05-30 17:09 ` Ted Dennison
  2002-05-30 17:29   ` Specialization Baugereau
  2002-05-31 19:44   ` Specialization Simon Wright
  2002-05-30 17:46 ` Specialization Toshitaka Kumano
  1 sibling, 2 replies; 22+ messages in thread
From: Ted Dennison @ 2002-05-30 17:09 UTC (permalink / raw)


"Baugereau" <baugereau@ifrance.kom> wrote in message news:<ad56du$pp4$1@wanadoo.fr>...
> For instance, when I empty the container, I want to Finalize all the
> elements if they are Controlled, and do nothing if not.

Why wouldn't that happen automaticly? If you want to *manually*
control finalization, you probably shouldn't be using controlled
types.



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

* Re: Specialization
  2002-05-30 17:09 ` Specialization Ted Dennison
@ 2002-05-30 17:29   ` Baugereau
  2002-05-30 19:20     ` Specialization Stephen Leake
  2002-05-31 19:44   ` Specialization Simon Wright
  1 sibling, 1 reply; 22+ messages in thread
From: Baugereau @ 2002-05-30 17:29 UTC (permalink / raw)


> "Baugereau" <baugereau@ifrance.kom> wrote in message
news:<ad56du$pp4$1@wanadoo.fr>...
> > For instance, when I empty the container, I want to Finalize all the
> > elements if they are Controlled, and do nothing if not.
>
> Why wouldn't that happen automaticly? If you want to *manually*
> control finalization, you probably shouldn't be using controlled
> types.

I have this interface in my package (I snipped)


with Ada.Finalization;
use Ada.Finalization;
generic
type ELEMENT is private;
package Vector is
Default_Reserved : constant NATURAL := 32;
Growth : constant NATURAL := 32;
type ELEMENTPTR is access all ELEMENT;
type ELEMENTS is array(NATURAL range <>) of aliased ELEMENT;
type ELEMENTSPTR is access ELEMENTS;
type VECTOR is new CONTROLLED with record
   Size : NATURAL;
   Reserved : NATURAL;
   Data : ELEMENTSPTR;
end record;

-- Controlled type
procedure Initialize (obj : in out VECTOR);
procedure Finalize (obj : in out VECTOR);
procedure Adjust (obj : in out VECTOR);

-- Custom
function Get (obj : in VECTOR; index : in NATURAL) return ELEMENTPTR;
function Get (obj : in VECTOR; index : in NATURAL) return ELEMENT;
procedure Push_Back (obj : in out VECTOR; elt : in ELEMENT);
procedure Empty (obj : in out VECTOR);
procedure Erase (obj : in out VECTOR; first : in NATURAL; last : in
NATURAL);
private
procedure Realloc (obj : in out VECTOR; new_reserved : in POSITIVE);
end Vector;


the goal is to have Data as a raw storage of ELEMENTs that I can extend when
I Push_Back elements in the VECTOR...
Data has Reserved elements but only Size elements are meaningful.
And if I push_back a lot of elements, I don't want to realloc the storage
each time, so I make it grow linearly (for now).

Then when I erase, reserved must stay the same, size should become 0, and
objects in the storage should be finalized if they are not trivial.
Is it clear this time? Sorry I'm not a native speaker :)

Is this inherently flawed?
Should I not bother with growing Data by myself? I don't think so, because I
think "new" is costly (it is just a belief :) )






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

* Re: Specialization
  2002-05-30 12:39 Specialization Baugereau
  2002-05-30 17:09 ` Specialization Ted Dennison
@ 2002-05-30 17:46 ` Toshitaka Kumano
  1 sibling, 0 replies; 22+ messages in thread
From: Toshitaka Kumano @ 2002-05-30 17:46 UTC (permalink / raw)


Hi,

Baugereau wrote:
> I'm trying to implement a generic container, say a extensible vector.
> But I'd like to specialize this component for controlled types.
> For instance, when I empty the container, I want to Finalize all the
> elements if they are Controlled, and do nothing if not.

Roughly speaking, Finalize for Controlled is equivalent to
"destructor" in C++, and usually it is called automatically
and implicitly when the object cease to live.

In usual usage when Finalize is called, you lose the container itself,
not only the elements :-)

So your statement "when I empty the container" is very strange to me
 because you seem to invoke explicitly...

> Is there a way, like in C++ (I come from a C++ background, maybe my view is
> too much "C++ template"-biased), to specialize the procedures of the package
> for some flavours of the generic parameter?

Guess from "template", you need not dynamic dispatching (virtual in C++).

Then my guess answer is:

  - use derived type simply (say C and Derived_C) 
    (not tagged, probably limited private)

  - implement different versions of "Empty" for two types
    (one for C does nothing (?), another for  Derived_C removes elements) 

Although I don't have much experience in C++ and could not give much help,
why don't you show your idea in some piece of code in C++ ?
Then you could get hints from some gurus who have experience both on C++
and on Ada.

--
Toshitaka Kumano
Kamakura
Japan



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

* Re: Specialization
  2002-05-30 17:29   ` Specialization Baugereau
@ 2002-05-30 19:20     ` Stephen Leake
  2002-05-30 19:48       ` Specialization Baugereau
  0 siblings, 1 reply; 22+ messages in thread
From: Stephen Leake @ 2002-05-30 19:20 UTC (permalink / raw)


"Baugereau" <baugereau@ifrance.kom> writes:

> > "Baugereau" <baugereau@ifrance.kom> wrote in message
> news:<ad56du$pp4$1@wanadoo.fr>...
> > > For instance, when I empty the container, I want to Finalize all the
> > > elements if they are Controlled, and do nothing if not.
> >
> > Why wouldn't that happen automaticly? If you want to *manually*
> > control finalization, you probably shouldn't be using controlled
> > types.
> 
> I have this interface in my package (I snipped)
> 
> 
> with Ada.Finalization;
> use Ada.Finalization;
> generic
> type ELEMENT is private;
> package Vector is
> Default_Reserved : constant NATURAL := 32;
> Growth : constant NATURAL := 32;
> type ELEMENTPTR is access all ELEMENT;
> type ELEMENTS is array(NATURAL range <>) of aliased ELEMENT;

This is the problem. You should (almost certainly :) have an array of
ELEMENTPTR, not an array of ELEMENT. When an element is added to
Vector, you call 'new' for it. When an element is erased from the
vector you call an instantiation of Unchecked_Deallocation on it. Then
Finalize will be called automatically, if necessary.

See the file sal-poly-unbounded_arrays.ads
in SAL at http://users.erols.com/leakstan/Stephe/Ada/sal.html
for an example of a similar package.

You will find that you will have to allow your generic ELEMENT type to
be unconstrained and/or indefinite, if the Vector package is to be
truly useful. For example, try to define a Vector of String. Once you
do that, you are forced to have an array of pointer-to-element.

-- 
-- Stephe



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

* Re: Specialization
  2002-05-30 19:20     ` Specialization Stephen Leake
@ 2002-05-30 19:48       ` Baugereau
  2002-05-31  1:18         ` Specialization Jim Rogers
  2002-05-31 13:27         ` Specialization Stephen Leake
  0 siblings, 2 replies; 22+ messages in thread
From: Baugereau @ 2002-05-30 19:48 UTC (permalink / raw)


> This is the problem. You should (almost certainly :) have an array of
> ELEMENTPTR, not an array of ELEMENT. When an element is added to
> Vector, you call 'new' for it. When an element is erased from the
> vector you call an instantiation of Unchecked_Deallocation on it. Then
> Finalize will be called automatically, if necessary.
>
> See the file sal-poly-unbounded_arrays.ads
> in SAL at http://users.erols.com/leakstan/Stephe/Ada/sal.html
> for an example of a similar package.
>
> You will find that you will have to allow your generic ELEMENT type to
> be unconstrained and/or indefinite, if the Vector package is to be
> truly useful. For example, try to define a Vector of String. Once you
> do that, you are forced to have an array of pointer-to-element.
>

Ok so this is the difference of philosophy with STL's vector, which is plain
value-oriented.
What I dislike here is the lack of locality of the elements, and the need to
"new" every time I add an element...
Any comment?





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

* Re: Specialization
  2002-05-30 19:48       ` Specialization Baugereau
@ 2002-05-31  1:18         ` Jim Rogers
  2002-05-31  5:41           ` Specialization Sergey Koshcheyev
  2002-05-31 13:27         ` Specialization Stephen Leake
  1 sibling, 1 reply; 22+ messages in thread
From: Jim Rogers @ 2002-05-31  1:18 UTC (permalink / raw)


Baugereau wrote:

> 
> Ok so this is the difference of philosophy with STL's vector, which is plain
> value-oriented.
> What I dislike here is the lack of locality of the elements, and the need to
> "new" every time I add an element...
> Any comment?


The difference is that in C++ you "new" the element before you add
it to the vector (in the constructor). You then pass a reference
(or pointer) to the vector. The C++ vector does not require heavy
weight copy semantics for add an element because it only really adds
a reference. The same is being done in Ada. The difference is that 
objects in C++ are so commonly passed by reference that you forget
what is going on. Ada is simply making the situation clear by requiring
you to dynamically allocate a copy of the object.

If you were to dynamically allocate all your objects in Ada, just as
you do in C++, then the container would not need to perform any of the
dynamic allocation. You could simply add references to the objects
just like you do in C++.

You will also find that Ada scoping rules are much more strict than C++
scoping rules. This can influence the way you design your container
package.

Jim Rogers





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

* Re: Specialization
  2002-05-31  1:18         ` Specialization Jim Rogers
@ 2002-05-31  5:41           ` Sergey Koshcheyev
  2002-05-31 11:36             ` Specialization Baugereau
  2002-05-31 14:08             ` Specialization Jim Rogers
  0 siblings, 2 replies; 22+ messages in thread
From: Sergey Koshcheyev @ 2002-05-31  5:41 UTC (permalink / raw)



"Jim Rogers" <jimmaureenrogers@worldnet.att.net> wrote in message
news:3CF6CF7D.8000704@worldnet.att.net...
> Baugereau wrote:
> > Ok so this is the difference of philosophy with STL's vector, which is
plain
> > value-oriented.
> > What I dislike here is the lack of locality of the elements, and the
need to
> > "new" every time I add an element...
> > Any comment?
>
> The difference is that in C++ you "new" the element before you add
> it to the vector (in the constructor).

This is wrong, if you have a vector<BigObject> in C++ STL, then what is
stored are BigObjects, not pointers to them. There are a few tricks that can
be used to achieve this ("placement new", and also the fact that it is
possible to call object destructors manually).

> If you were to dynamically allocate all your objects in Ada, just as
> you do in C++, then the container would not need to perform any of the
> dynamic allocation. You could simply add references to the objects
> just like you do in C++.

When using STL containers, you can add a local object into the container,
for example, and it will be properly copied.

> You will also find that Ada scoping rules are much more strict than C++
> scoping rules. This can influence the way you design your container
> package.

The scoping rules are not the problem, I think. You can copy the objects, if
needed. To imitate C++ in this respect, you just need some way (possibly, a
hack) to manually Initialize and Finalize the inserted objects, and ensure
that the compiler doesn't also try to do that. Maybe playing with
Storage_Pools a little will lead to a solution. Or maybe there is a more
Ada-like way, I don't know.

Sergey.





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

* Re: Specialization
  2002-05-31  5:41           ` Specialization Sergey Koshcheyev
@ 2002-05-31 11:36             ` Baugereau
  2002-05-31 14:08             ` Specialization Jim Rogers
  1 sibling, 0 replies; 22+ messages in thread
From: Baugereau @ 2002-05-31 11:36 UTC (permalink / raw)



> > The difference is that in C++ you "new" the element before you add
> > it to the vector (in the constructor).
>
> This is wrong, if you have a vector<BigObject> in C++ STL, then what is
> stored are BigObjects, not pointers to them. There are a few tricks that
can
> be used to achieve this ("placement new", and also the fact that it is
> possible to call object destructors manually).

Exactly. This is what I was talking about :)
I want contiguity (is this English, I'm not sure :) ) of all the elements in
the container.

>
> > If you were to dynamically allocate all your objects in Ada, just as
> > you do in C++, then the container would not need to perform any of the
> > dynamic allocation. You could simply add references to the objects
> > just like you do in C++.
>
> When using STL containers, you can add a local object into the container,
> for example, and it will be properly copied.
>
> > You will also find that Ada scoping rules are much more strict than C++
> > scoping rules. This can influence the way you design your container
> > package.
>
> The scoping rules are not the problem, I think. You can copy the objects,
if
> needed. To imitate C++ in this respect, you just need some way (possibly,
a
> hack) to manually Initialize and Finalize the inserted objects, and ensure
> that the compiler doesn't also try to do that. Maybe playing with
> Storage_Pools a little will lead to a solution. Or maybe there is a more
> Ada-like way, I don't know.

I'll check the storage pools in the ARM. Thanks.





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

* Re: Specialization
  2002-05-30 19:48       ` Specialization Baugereau
  2002-05-31  1:18         ` Specialization Jim Rogers
@ 2002-05-31 13:27         ` Stephen Leake
  2002-05-31 19:46           ` Specialization Simon Wright
  1 sibling, 1 reply; 22+ messages in thread
From: Stephen Leake @ 2002-05-31 13:27 UTC (permalink / raw)


"Baugereau" <baugereau@ifrance.kom> writes:

> > This is the problem. You should (almost certainly :) have an array of
> > ELEMENTPTR, not an array of ELEMENT. When an element is added to
> > Vector, you call 'new' for it. When an element is erased from the
> > vector you call an instantiation of Unchecked_Deallocation on it. Then
> > Finalize will be called automatically, if necessary.
> >
> > See the file sal-poly-unbounded_arrays.ads
> > in SAL at http://users.erols.com/leakstan/Stephe/Ada/sal.html
> > for an example of a similar package.
> >
> > You will find that you will have to allow your generic ELEMENT type to
> > be unconstrained and/or indefinite, if the Vector package is to be
> > truly useful. For example, try to define a Vector of String. Once you
> > do that, you are forced to have an array of pointer-to-element.
> >
> 
> Ok so this is the difference of philosophy with STL's vector, which is plain
> value-oriented.
> What I dislike here is the lack of locality of the elements, and the need to
> "new" every time I add an element...
> Any comment?

I should have mentioned that there are other ways to get the Finalize
procedure called, without using Unchecked_Deallocation. 

Perhaps the cleanest is to require the client to pass in a
"Null_Value" object:

generic
   type Element is private;
   Null_Value : in Element;
package Foo is

   type Element_array is array (1 .. 10) of Element;

   procedure Empty (Item : in out Element_Array);

end Foo;

Then in the body of Empty you fill the array with Null_Value by
assignment. If Element is Controlled, this will call Finalize on the
values in the array. It is up to the client to ensure that Null_Value
is sufficiently small to not be a burden when copied lots of times.

Another way is to require the type to be derived from Controlled:

generic
   type element is new Ada.Finalization.Controlled;
package foo is
...
end foo;

But then this package is not useful for non-controlled types.

One more: require the client to pass in a Finalize procedure:

generic
   type Element is private;
   with procedure Finalize (Item : in out Element) is <>;
package Foo is
   type Element_array is array (1 .. 10) of Element;

   procedure Empty (Item : in out Element_Array);

end Foo;

Now Empty can call Finalize on each element of the array. For
non-controlled types, Finalize can be a null operation. This is the
approach I use in SAL; it allows a generic package to be
instantiated with the widest range of types.

-- 
-- Stephe



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

* Re: Specialization
  2002-05-31  5:41           ` Specialization Sergey Koshcheyev
  2002-05-31 11:36             ` Specialization Baugereau
@ 2002-05-31 14:08             ` Jim Rogers
  2002-05-31 16:45               ` Specialization Hyman Rosen
  2002-05-31 17:05               ` Specialization Sergey Koshcheyev
  1 sibling, 2 replies; 22+ messages in thread
From: Jim Rogers @ 2002-05-31 14:08 UTC (permalink / raw)


"Sergey Koshcheyev" <serko84@hotmail.com> wrote in message news:<ad72e5$e9c$1@ns.felk.cvut.cz>...
> "Jim Rogers" <jimmaureenrogers@worldnet.att.net> wrote in message
> news:3CF6CF7D.8000704@worldnet.att.net...
> > Baugereau wrote:
> > > Ok so this is the difference of philosophy with STL's vector, which is
>  plain
> > > value-oriented.
> > > What I dislike here is the lack of locality of the elements, and the
>  need to
> > > "new" every time I add an element...
> > > Any comment?
> >
> > The difference is that in C++ you "new" the element before you add
> > it to the vector (in the constructor).
> 
> This is wrong, if you have a vector<BigObject> in C++ STL, then what is
> stored are BigObjects, not pointers to them. There are a few tricks that can
> be used to achieve this ("placement new", and also the fact that it is
> possible to call object destructors manually).

You got me there. My ignorant message assumed you were correct when you claimed
that the C++ STL did not need to allocate nodes in its container classes.

I have since done a little research on the web. I see that the STL container
classes do indeed allocate objects and copy them. This is clearly documented
in http://www.sgi.com/tech/stl/alloc.html 

After reading the above reference I see no significant difference between
the problems you encountered in Ada and the way the C++ STL is currently
implemented (regarding node allocation). Note that the SGI document states
that their allocator uses malloc rather than new. I am not sure this is
a big performance or safety advantage. It may be more flexible than the C++
new operator.

You clearly understand how to use the C++ STL. Have you ever implemented
the C++ STL before? I think you are only now encountering the low level
details which must exist in the C++ STL.

Jim Rogers



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

* Re: Specialization
  2002-05-31 14:08             ` Specialization Jim Rogers
@ 2002-05-31 16:45               ` Hyman Rosen
  2002-05-31 17:05               ` Specialization Sergey Koshcheyev
  1 sibling, 0 replies; 22+ messages in thread
From: Hyman Rosen @ 2002-05-31 16:45 UTC (permalink / raw)


Jim Rogers wrote:
> You got me there. My ignorant message assumed you were correct when you claimed
> that the C++ STL did not need to allocate nodes in its container classes.
> 
> I have since done a little research on the web. I see that the STL container
> classes do indeed allocate objects and copy them. This is clearly documented
> in http://www.sgi.com/tech/stl/alloc.html 
> 
> After reading the above reference I see no significant difference between
> the problems you encountered in Ada and the way the C++ STL is currently
> implemented (regarding node allocation).

Note that for vector, there is not "node allocation". Rather, space
for the entire vector is allocated in one allocation, and the objects
of the vector are built in place in the allocated memory. If the
vector needs to be grown beyond its current capacity, twice as much
memory is allocated, so appending takes constant amortized time. The
elements of a vector are contiguous, just as if they were in an array.

Here's a simplified version of how this looks in C++:

template<typename T> T *make_array(size_t n, const T &prototype)
{
	// allocate uninitialized storage for n T objects
	T *array = static_cast<T *>(::operator new(n * sizeof(T)));
	// construct each array object in place from prototype
	for (size_t i = 0; i < n; ++i)
		new (array + i) T(prototype);
	return array;
}

template<typename T> void destroy_array(size_t n, const T *array)
{
	// destruct each array object in place; storage unaffected
	for (size_t i = 0; i < n; ++i)
		array[i].~T();
	// deallocate storage
	::operator delete(array);
}




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

* Re: Specialization
  2002-05-31 14:08             ` Specialization Jim Rogers
  2002-05-31 16:45               ` Specialization Hyman Rosen
@ 2002-05-31 17:05               ` Sergey Koshcheyev
  2002-05-31 17:40                 ` Specialization Hyman Rosen
  1 sibling, 1 reply; 22+ messages in thread
From: Sergey Koshcheyev @ 2002-05-31 17:05 UTC (permalink / raw)


Just a clarification, I'm not the original poster who wanted to implement
STL in Ada, I have only jumped in to correct a little misinformation.


"Jim Rogers" <jimmaureenrogers@worldnet.att.net> wrote in message
news:82347202.0205310608.2f7d634d@posting.google.com...

> After reading the above reference I see no significant difference between
> the problems you encountered in Ada and the way the C++ STL is currently
> implemented (regarding node allocation). Note that the SGI document states
> that their allocator uses malloc rather than new. I am not sure this is
> a big performance or safety advantage. It may be more flexible than the
C++
> new operator.

Regardless of what the allocator uses, you only get a pointer to a block of
memory from it. You then need to construct the object, and often not at the
time of the allocation, but later. However, calling a constructor explicitly
is not allowed, so this is where the "hacks" come into the picture. If you
look at the STL documentation, you will find a function 'construct', which
implements such delayed construction.

If there is a way to have this idiom ("delayed initialization") in Ada, this
is what is needed. If there was a more Ada-like way to achieve a similar
effect, like for example having space allocated for 8 items in a vector, but
having only the first three items fully constructed (initialized) and
usable, it would be even better.

> You clearly understand how to use the C++ STL. Have you ever implemented
> the C++ STL before? I think you are only now encountering the low level
> details which must exist in the C++ STL.

No, I haven't implemented the STL. And I don't even exactly remember the
source of my knowledge about it :-)

Sergey.





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

* Re: Specialization
  2002-05-31 17:05               ` Specialization Sergey Koshcheyev
@ 2002-05-31 17:40                 ` Hyman Rosen
  2002-05-31 20:04                   ` Specialization Sergey Koshcheyev
  0 siblings, 1 reply; 22+ messages in thread
From: Hyman Rosen @ 2002-05-31 17:40 UTC (permalink / raw)


Sergey Koshcheyev wrote:
 > However, calling a constructor explicitly
> is not allowed, so this is where the "hacks"
 > come into the picture.

This is called "placement new", and is a fully blessed
part of standard C++. There is no justification for
calling it a "hack". There is nothing unreasonable in
separating reservation of memory from construction of
objects, and indeed, that is what "ordinary" new does
as well.




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

* Re: Specialization
  2002-05-30 17:09 ` Specialization Ted Dennison
  2002-05-30 17:29   ` Specialization Baugereau
@ 2002-05-31 19:44   ` Simon Wright
  2002-06-01 15:25     ` Specialization Stephen Leake
  1 sibling, 1 reply; 22+ messages in thread
From: Simon Wright @ 2002-05-31 19:44 UTC (permalink / raw)


dennison@telepath.com (Ted Dennison) writes:

> Why wouldn't that happen automaticly? If you want to *manually*
> control finalization, you probably shouldn't be using controlled
> types.

I _knew_ there was a problem in the Booch Containers around here
... if you use a bounded container it places the elements in an array,
so if they need finalization it may well happen long after you were
expecting it to. I guess I'd need to add something to the generic ..

   generic
      type Item is private;
      with function "=" (L, R : Item) return Boolean is <>;
      Null_Value : Item;                                    --  new
   package BC.Containers is

which means yet another non-defaultable generic parameter, people are
fed up enough with instantiating all these nested generics as it is. I
suppose this could be deferred to the forms that need it, clearly
Unbounded doesn't:

   generic
      type Item is private;
      with function "=" (L, R : Item) return Boolean is <>;
   package BC.Containers is

   generic
      Maximum_Size : Positive;
      Null_Value : Item;                                     -- new
   package BC.Containers.Collections.Bounded is

   generic
      Storage : in out System.Storage_Pools.Root_Storage_Pool'Class;
   package BC.Containers.Collections.Unbounded is




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

* Re: Specialization
  2002-05-31 13:27         ` Specialization Stephen Leake
@ 2002-05-31 19:46           ` Simon Wright
  2002-06-01 15:30             ` Specialization Stephen Leake
  0 siblings, 1 reply; 22+ messages in thread
From: Simon Wright @ 2002-05-31 19:46 UTC (permalink / raw)


Stephen Leake <stephen.a.leake.1@gsfc.nasa.gov> writes:

> One more: require the client to pass in a Finalize procedure:
> 
> generic
>    type Element is private;
>    with procedure Finalize (Item : in out Element) is <>;
> package Foo is
>    type Element_array is array (1 .. 10) of Element;
> 
>    procedure Empty (Item : in out Element_Array);
> 
> end Foo;
> 
> Now Empty can call Finalize on each element of the array. For
> non-controlled types, Finalize can be a null operation. This is the
> approach I use in SAL; it allows a generic package to be
> instantiated with the widest range of types.

I like this.

The Element probably has to be visibly (to the client) controlled, for
her to get hold of the Finalize.



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

* Re: Specialization
  2002-05-31 17:40                 ` Specialization Hyman Rosen
@ 2002-05-31 20:04                   ` Sergey Koshcheyev
  2002-05-31 21:25                     ` Specialization Hyman Rosen
  0 siblings, 1 reply; 22+ messages in thread
From: Sergey Koshcheyev @ 2002-05-31 20:04 UTC (permalink / raw)


"Hyman Rosen" <hyrosen@mail.com> wrote in message
news:3CF7B571.2090901@mail.com...
> This is called "placement new", and is a fully blessed
> part of standard C++. There is no justification for
> calling it a "hack". There is nothing unreasonable in
> separating reservation of memory from construction of
> objects, and indeed, that is what "ordinary" new does
> as well.

Yes, of course, that's why I put quotes around "hack". It was meant as
"not-really-a-hack". As for ordinary new, it does return you a pointer to a
fully initialized object, doesn't it?

Anyway, describing anything as hack, quotes or not, is quite subjective, so
I'm not going to defend my point of view any further.

Sergey.





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

* Re: Specialization
  2002-05-31 20:04                   ` Specialization Sergey Koshcheyev
@ 2002-05-31 21:25                     ` Hyman Rosen
  0 siblings, 0 replies; 22+ messages in thread
From: Hyman Rosen @ 2002-05-31 21:25 UTC (permalink / raw)


Sergey Koshcheyev wrote:
 > As for ordinary new, it does return you a pointer to a
> fully initialized object, doesn't it?

As does placement new. It's one of those silly overloaded
C++isms again. There are two news. One is 'new-expression',
and it is this that returns a pointer to a fully initialized
object. The other is 'operator new' which returns a pointer
to allocated but uninitialized storage. The 'new-expression'
first calls 'operator new' to allocate storage, then builds
the initialized object(s) in that storage.

The key is that 'operator new' is actually an overloaded
family of functions. One of those overloads takes an extra
pointer parameter and simply returns it, and that is the
form generally known as 'placement new'. That is, ordinary
'operator new' calls malloc (essentially) to get storage
for the allocated object, while placement 'operator new'
simply hands back what you give it, namely previously
allocated storage.

The syntax of a 'new-expression' includes the ability to
specify additional parameters for 'operator new', which
allows it to use placement 'operator new'.




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

* Re: Specialization
  2002-05-31 19:44   ` Specialization Simon Wright
@ 2002-06-01 15:25     ` Stephen Leake
  2002-06-01 17:12       ` Specialization Simon Wright
  0 siblings, 1 reply; 22+ messages in thread
From: Stephen Leake @ 2002-06-01 15:25 UTC (permalink / raw)


Simon Wright <simon@pushface.org> writes:

> dennison@telepath.com (Ted Dennison) writes:
> 
> > Why wouldn't that happen automaticly? If you want to *manually*
> > control finalization, you probably shouldn't be using controlled
> > types.
> 
> I _knew_ there was a problem in the Booch Containers around here
> ... if you use a bounded container it places the elements in an array,
> so if they need finalization it may well happen long after you were
> expecting it to. I guess I'd need to add something to the generic ..
> 
>    generic
>       type Item is private;
>       with function "=" (L, R : Item) return Boolean is <>;
>       Null_Value : Item;                                    --  new
>    package BC.Containers is
> 
> which means yet another non-defaultable generic parameter, 

Things should be as simple as possible, but no simpler. Put it in. 

You could actually give it a default, but the users would have to make
that object visible, and use your name for it; not much better than
simply supplying the parameter at instantiation.

> people are fed up enough with instantiating all these nested
> generics as it is. 

BCs are for experts. Tell them to suck it up :).

> I suppose this could be deferred to the forms that need it, clearly
> Unbounded doesn't:

Yes, localize the dependencies as much as possible.

-- 
-- Stephe



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

* Re: Specialization
  2002-05-31 19:46           ` Specialization Simon Wright
@ 2002-06-01 15:30             ` Stephen Leake
  0 siblings, 0 replies; 22+ messages in thread
From: Stephen Leake @ 2002-06-01 15:30 UTC (permalink / raw)


Simon Wright <simon@pushface.org> writes:

> Stephen Leake <stephen.a.leake.1@gsfc.nasa.gov> writes:
> 
> > One more: require the client to pass in a Finalize procedure:
> > 
> > generic
> >    type Element is private;
> >    with procedure Finalize (Item : in out Element) is <>;
> > package Foo is
> >    type Element_array is array (1 .. 10) of Element;
> > 
> >    procedure Empty (Item : in out Element_Array);
> > 
> > end Foo;
> > 
> > Now Empty can call Finalize on each element of the array. For
> > non-controlled types, Finalize can be a null operation. This is the
> > approach I use in SAL; it allows a generic package to be
> > instantiated with the widest range of types.
> 
> I like this.
> 
> The Element probably has to be visibly (to the client) controlled, for
> her to get hold of the Finalize.

Either that, or some "Free" operation is visible. 

In SAL, I actually call this parameter "Free_Item", not "Finalize". I
was focussed more on the constrained/unconstrained and
definite/indefinite issues, which determine whether the container
elements are allocated or not, rather than on Controlled types. But
the same mechanism works for both, which is why I use it.

-- 
-- Stephe



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

* Re: Specialization
  2002-06-01 15:25     ` Specialization Stephen Leake
@ 2002-06-01 17:12       ` Simon Wright
  2002-06-01 19:50         ` Specialization Stephen Leake
  0 siblings, 1 reply; 22+ messages in thread
From: Simon Wright @ 2002-06-01 17:12 UTC (permalink / raw)


Stephen Leake <stephen.a.leake.1@gsfc.nasa.gov> writes:

> You could actually give it a default, but the users would have to make
> that object visible, and use your name for it; not much better than
> simply supplying the parameter at instantiation.

I don't think so, it's their type not mine

> > people are fed up enough with instantiating all these nested
> > generics as it is. 
> 
> BCs are for experts. Tell them to suck it up :).

How to win friends ..!



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

* Re: Specialization
  2002-06-01 17:12       ` Specialization Simon Wright
@ 2002-06-01 19:50         ` Stephen Leake
  0 siblings, 0 replies; 22+ messages in thread
From: Stephen Leake @ 2002-06-01 19:50 UTC (permalink / raw)


Simon Wright <simon@pushface.org> writes:

> Stephen Leake <stephen.a.leake.1@gsfc.nasa.gov> writes:
> 
> > You could actually give it a default, but the users would have to make
> > that object visible, and use your name for it; not much better than
> > simply supplying the parameter at instantiation.
> 
> I don't think so, it's their type not mine

Hmm. You seem to be correct. I was mislead by ARM 12.4:

  2.      formal_object_declaration ::=
             defining_identifier_list : mode subtype_mark
               [:= default_expression];

                          *Name Resolution Rules*

  3. The expected type for the default_expression, if any, of a formal
     object is the type of the formal object.

I assumed the 'default_expression' was resolved at the point of instantiation,
not at the point of declaration of the generic. But I now see that
doesn't make sense.

Learn something new every day :).

Here's code to prove your point. It fails because 'A_Null_Value' is
not visible at it's first occurance.

with Ada.Text_IO; use Ada.Text_IO;
procedure Formal_Default
is
   type My_Type is record
      Foo : Integer;
   end record;

   generic
      type Gen_Type is private;
      Null_Value : in Gen_Type := A_Null_Value; -- wrong; not visible.
      with function Image (Item : in Gen_Type) return String is <>;
   procedure Gen_Bar;

   procedure Gen_Bar
   is begin
      Put_Line (Image (Null_Value));
   end Gen_Bar;

   function Image (Item : in My_Type) return String
   is begin
      return Integer'Image (Item.Foo);
   end Image;

   A_Null_Value : constant My_Type := (Foo => 0);

   procedure Bar is new Gen_Bar (My_Type);
begin
   Bar;
end Formal_Default;


-- 
-- Stephe



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

end of thread, other threads:[~2002-06-01 19:50 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-05-30 12:39 Specialization Baugereau
2002-05-30 17:09 ` Specialization Ted Dennison
2002-05-30 17:29   ` Specialization Baugereau
2002-05-30 19:20     ` Specialization Stephen Leake
2002-05-30 19:48       ` Specialization Baugereau
2002-05-31  1:18         ` Specialization Jim Rogers
2002-05-31  5:41           ` Specialization Sergey Koshcheyev
2002-05-31 11:36             ` Specialization Baugereau
2002-05-31 14:08             ` Specialization Jim Rogers
2002-05-31 16:45               ` Specialization Hyman Rosen
2002-05-31 17:05               ` Specialization Sergey Koshcheyev
2002-05-31 17:40                 ` Specialization Hyman Rosen
2002-05-31 20:04                   ` Specialization Sergey Koshcheyev
2002-05-31 21:25                     ` Specialization Hyman Rosen
2002-05-31 13:27         ` Specialization Stephen Leake
2002-05-31 19:46           ` Specialization Simon Wright
2002-06-01 15:30             ` Specialization Stephen Leake
2002-05-31 19:44   ` Specialization Simon Wright
2002-06-01 15:25     ` Specialization Stephen Leake
2002-06-01 17:12       ` Specialization Simon Wright
2002-06-01 19:50         ` Specialization Stephen Leake
2002-05-30 17:46 ` Specialization Toshitaka Kumano

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