473,461 Members | 1,491 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

Teaching new tricks to an old dog (C++ -->Ada)

I 'm following various posting in "comp.lang.ada, comp.lang.c++ ,
comp.realtime, comp.software-eng" groups regarding selection of a
programming language of C, C++ or Ada for safety critical real-time
applications. The majority of expert/people recommend Ada for safety
critical real-time applications. I've many years of experience in C/C++ (and
Delphi) but no Ada knowledge.

May I ask if it is too difficult to move from C/C++ to Ada?
What is the best way of learning Ada for a C/C++ programmer?

Jul 23 '05
822 28875
"Jerry Coffin" writes:
Ludovic Brenta wrote:
I could make the code less verbose by using use clauses, similar to
"using namespace std" which you seem fond of. In avionics, our
coding standards forbid that because we want everything to be
explicit.


A poor idea. Just for example, consider writing a generic sorting
function. It needs to swap items that it's sorting. In well-written
C++, this will often be done with a using clause. Specifically, if
the type of items has provided its own specialized version of swap,
then my sorting functino should use that, but otherwise it should
use std::swap to swap them.

I try to specify whatever_type::swap(x,y), then compilation will
fail if the type has not provided a swap function. Conversely, if I
specify std::swap(x,y), then the specialized swap function won't be
used for those types that provide one.


Ada requires explicit instanciation of all templates, so there is no
"default". We do not have problems using fully-qualified names.

Ada 95's object-oriented features do not suffer from this either.

package P is
type Base is tagged null record;

procedure Method (B : in Base);
end P;
with P;
package Q is
type Derived is new P.Base with private;

procedure Method (B : in Derived); -- overloads P.Method
private
-- omitted
end Q;
with P;
procedure Dynamic_Dispatch (B : in Base'Class) is
begin
P.Method (B); -- [1]
end Dynamic_Dispatch;

The procedure Dynamic_Dispatch does not see package Q, yet it can call
Q.Derived if it receives an instance of Q.Derived as its parameter.
This, *even* without a use clause.

--
Ludovic Brenta.
Jul 23 '05 #151
On Tue, 08 Mar 2005 13:33:33 -0500, CTips wrote:
How easy is it to build an arena allocator in Ada?
It is trivial:

type Object is ...;
type Object_Ptr is access Object;
for Object_Ptr'Storage_Pool use My_Arena;

Here you are:

Ptr : Object_Ptr := new Object; -- This allocates it in My_Arena

Note that Object can still be allocated on the stack or in any other pool:

type Object_Universal_Ptr is access all Object;

This : Object;
-- This allocates it on the stack
That : Object_Universal_Ptr := new Object;
-- This will be in the(a) default pool (in the heap)
Given a processor with load-word-locked and store-word-conditional, how
would I build an atomic increment function?


Why should I have atomic increment function? Ada has native concurrency
support. But if somebody would need that extremely low level thing as
atomic integers, then:

protected type Atomic_Integer is
procedure Increment;
private
Value : Integer;
end Atomic_Integer;

-- Implementation
protected body Atomic_Integer is
procedure Increment is
begin
Value := Value + 1;
end Increment;
end Atomic_Integer;

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Jul 23 '05 #152
Jerry Coffin wrote:
In fact,
any software system over a half-million lines of
source code should be coded in
Ada.


Here, however, you lose your grip on reality. This is NOT "in fact" --
it's purely an OPINION! It's certainly possible to find projects that
would involve more than a half-million lines of code for which Ada
would be _extremely_ poorly suited, at best.


It's an opinion /nearly/ shared with P. J. Plauger of the ANSI-C
committee (and Dinkumware) - only I believe he quoted 100 thousand lines
as the point at which you should be using Ada. :-)

Cheers

-- Martin
Jul 23 '05 #153
Pascal Obry wrote:
CTips <ct***@bestweb.net> writes:

Free? Well, lets look at one particular issue: pointers to arbitrary
locations. In C, its a common idiom to do the following:
foo(int * p)
{
int * z;
for( i ... ) {
... p[i]...;
}
z = p;
}

...
foo( &x[lo] );
...

Now, how can *any* language check to see that p[i] is within bounds?

Good you asked! Let's code this example in Ada (using Ada and
not C/C++ style, in Ada for the above example we do not need a pointer):

type T is array (Positive range <>) of Integer;

procedure Foo (P : in out T) is
Z : Positive;
begin
for I in P'Range loop
... P(i)...;
-- Here P(i) is always within the bounds, no check needed.
end loop;
Z := P'First;


Nope, not z = p[0], z = p; Z is a _pointer_ to int, not an int.
end Foo;

...

Foo (X (Lo .. X'Last));

Bullsh*t. In several ways, of which two are:

Given your assumption about maybe you just don't know Ada.


Try again. Show me how sizeof(z) != 8 in Ada.

Pascal.

Jul 23 '05 #154
Dmitry A. Kazakov wrote:
On Tue, 08 Mar 2005 13:33:33 -0500, CTips wrote:

How easy is it to build an arena allocator in Ada?

It is trivial:

type Object is ...;
type Object_Ptr is access Object;
for Object_Ptr'Storage_Pool use My_Arena;

Here you are:

Ptr : Object_Ptr := new Object; -- This allocates it in My_Arena


And how is My_Arena defined? Is it just a blob of memory? Or is it a
"class" that can invoke sbrk (or whatever) when it needs to?

Note that Object can still be allocated on the stack or in any other pool:

type Object_Universal_Ptr is access all Object;

This : Object;
-- This allocates it on the stack
That : Object_Universal_Ptr := new Object;
-- This will be in the(a) default pool (in the heap)

Given a processor with load-word-locked and store-word-conditional, how
would I build an atomic increment function?

Why should I have atomic increment function? Ada has native concurrency
support. But if somebody would need that extremely low level thing as
atomic integers, then:

protected type Atomic_Integer is
procedure Increment;
private
Value : Integer;
end Atomic_Integer;

-- Implementation
protected body Atomic_Integer is
procedure Increment is
begin
Value := Value + 1;
end Increment;
end Atomic_Integer;


Will that generate:
L0:
lwlock temp,&Value
add temp,temp,1
stwcond temp,&Value
if( failed ) goto L0;
or will it generate something much more heavy-weight.
Jul 23 '05 #155
In article <1i******************************@40tude.net>, "Dmitry A. Kazakov" <ma*****@dmitry-kazakov.de> writes:
On Tue, 08 Mar 2005 13:33:33 -0500, CTips wrote:

Given a processor with load-word-locked and store-word-conditional, how
would I build an atomic increment function?


Why should I have atomic increment function? Ada has native concurrency
support. But if somebody would need that extremely low level thing as
atomic integers, then:

protected type Atomic_Integer is
procedure Increment;
private
Value : Integer;
end Atomic_Integer;

-- Implementation
protected body Atomic_Integer is
procedure Increment is
begin
Value := Value + 1;
end Increment;
end Atomic_Integer;


In other words, the code generator within the Ada compiler takes care
of the load-locked store-conditional aspects of the architecture.

What Dmitry has shown is how the programmer accesses that capability.
Jul 23 '05 #156

CTips <ct***@bestweb.net> writes:
Nope, not z = p[0], z = p; Z is a _pointer_ to int, not an int.
Look at your program. You do nothing with Z so my solution is equivalent.
That's the point.
Try again. Show me how sizeof(z) != 8 in Ada.


Sorry I don't parse this one. I don't care about the size of Z! I care about
what my application has to do. So if you tell us what you want to achieve we'll
provide the solution using Ada not Ada-Transtaled-From-C++ one. It is always a
mistake to copy the solution word for word when translating from one language
to another.

chauve-souris /= bald-mouse

Pascal.

--

--|------------------------------------------------------
--| Pascal Obry Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--| http://www.obry.org
--| "The best way to travel is by means of imagination"
--|
--| gpg --keyserver wwwkeys.pgp.net --recv-key C1082595
Jul 23 '05 #157
CTips wrote:
Dmitry A. Kazakov wrote:
type Object is ...;
type Object_Ptr is access Object;
for Object_Ptr'Storage_Pool use My_Arena;

Here you are:

Ptr : Object_Ptr := new Object; -- This allocates it in My_Arena

And how is My_Arena defined? Is it just a blob of memory? Or is it a
"class" that can invoke sbrk (or whatever) when it needs to?


My_Arena is a storage pool, storage pool is a term
defined by the language.
Will that generate:
L0:
lwlock temp,&Value
add temp,temp,1
stwcond temp,&Value
if( failed ) goto L0;
or will it generate something much more heavy-weight.


For how many concurrently executing threads
of control, each invoking the incrementing function,
will this work? (Without any addition that is, as in
the Ada example)

Georg
Jul 23 '05 #158
On Tue, 08 Mar 2005 15:13:20 -0500, CTips wrote:
Dmitry A. Kazakov wrote:
On Tue, 08 Mar 2005 13:33:33 -0500, CTips wrote:
How easy is it to build an arena allocator in Ada?


It is trivial:

type Object is ...;
type Object_Ptr is access Object;
for Object_Ptr'Storage_Pool use My_Arena;

Here you are:

Ptr : Object_Ptr := new Object; -- This allocates it in My_Arena


And how is My_Arena defined? Is it just a blob of memory? Or is it a
"class" that can invoke sbrk (or whatever) when it needs to?


It is completely up to you. My_Arena has to be derived from
System.Storage_Pools.Root_Storage_Pool. Which is the abstract base of all
storage pools. The implementation of Allocate and Deallocate is at your
discretion. For an arena the pool may contain a statically allocated array
organized as a stack. Deallocate could be then void, or it can pop
everything above it as in mark'n'release. A more advanced application could
allocate memory in segments at request etc. For a sample implementation of
a segmented stack pool see:

http://www.dmitry-kazakov.de/ada/com....htm#Pools_etc
Given a processor with load-word-locked and store-word-conditional, how
would I build an atomic increment function?


Why should I have atomic increment function? Ada has native concurrency
support. But if somebody would need that extremely low level thing as
atomic integers, then:

protected type Atomic_Integer is
procedure Increment;
private
Value : Integer;
end Atomic_Integer;

-- Implementation
protected body Atomic_Integer is
procedure Increment is
begin
Value := Value + 1;
end Increment;
end Atomic_Integer;

Will that generate:
L0:
lwlock temp,&Value
add temp,temp,1
stwcond temp,&Value
if( failed ) goto L0;
or will it generate something much more heavy-weight.


Ask your compiler vendor. Though it wouldn't be necessarily polling. Also
usually protected objects are not used for so utterly fine-grained mutual
exclusion/locking. Atomic integer increment is normally just a small part
of some larger (but not lengthy) operation. For example, placing something
in a queue. Therefore spinning for a lock (which probably would be the
implementation) will likely be less expensive than some tricky guards
attached to each and every instruction. Note also that at such a low level
it would be very difficult if possible to maintain data consistency.
Compiler simply does not know what is related to what and will try to cope
with the worst case scenario. Protected types in Ada are to describe this
sort of semantics. So in the end atomic integers are pretty useless, no
matter how efficient they could be implemented.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Jul 23 '05 #159

CTips <ct***@bestweb.net> writes:
protected type Atomic_Integer is
procedure Increment;
private
Value : Integer;
end Atomic_Integer;
-- Implementation
protected body Atomic_Integer is
procedure Increment is
begin
Value := Value + 1;
end Increment;
end Atomic_Integer;


Will that generate:
L0:
lwlock temp,&Value
add temp,temp,1
stwcond temp,&Value
if( failed ) goto L0;
or will it generate something much more heavy-weight.


No protected type implementations will be so light. This is impossible as it
brings far more than atomic integer. For an atomic integer it is possible to
declare :

Value : Integer;
pragma Atomic (Value);

In this case it would be nice to see the generated code.

Pascal.

--

--|------------------------------------------------------
--| Pascal Obry Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--| http://www.obry.org
--| "The best way to travel is by means of imagination"
--|
--| gpg --keyserver wwwkeys.pgp.net --recv-key C1082595
Jul 23 '05 #160
CTips wrote:
int * z;
Try again. Show me how sizeof(z) != 8 in Ada.
I'm not sure I understand. On an x86 system,

type Tiny is range 0 .. 31;
-- stored in an 8 bits register unless I demand otherwise

Type TP is access all Tiny;
for TP'Size use 32; -- in bits.

Ask for more bits for the pointer if you like. E.g.,

for TP'Size use 128;

In this case you get a compiler warning about unused bits. Then,
without any optimization, I get diffs of this sort, reflecting
the difference in the sizes of the pointer types TP:

< subl $8, %esp
--- subl $40, %esp 32,33c32,33
< leal -1(%ebp), %eax
< movl %eax, -8(%ebp)
--- leal -9(%ebp), %eax
movl %eax, -40(%ebp)

Jul 23 '05 #161
CTips wrote:
Nope, not z = p[0], z = p; Z is a _pointer_ to int, not an int.


Well, yes. Nothing stops you from passing a pointer to an int
in Ada, in both read-only and read-write mode.
And you can of course have pointers to arbitraty locations but you
have to use language to express this fact, using for example

for X'Adress use ...;

Or use the adressing types and operations in the System hierarchy.

You can also use any bit pattern to represent anything as long as
you explicitly ask for a new interpretation. Isn't this slightly more
permissive than what can be expressed using reinterpret_cast in C++?

Also, Unchecked_Conversion is neither casting, nor the usual type
conversion.
If I wanted the bits of a 32 bits float of value 3.14 to stand for an
integer, type conversion will give 3, an instance of Unchecked_Conversion
will give 1078523331.

Georg
Jul 23 '05 #162
Falk Tannhäuser wrote:
Furthermore, the implementer of "whatever_type" should consider to
put the specialisation of "swap" into the "std" namespace, which
is possible by § 17.4.3.1/1 of the Standard.


Too tricky, can become bad habit.

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #163
John Hudak wrote:
What?????????????????????????????????????????????? ??? Assembly language?
powerful? If you decide to write a X GUI interface in assembly, I'll
check in on you in 20 years to see how your doing.... Higher level
languages handle broader abstract concepts better than low level
languages. Assembly is great if you are optimizing device drivers or
banging bits at the hardware register level...not good at implementing
scientific algorithms, GUIs, databases, etc. There are thousands of
reasearch papers that extol the problems of assembly language approach
to things, and yes, there are places and reasons to use it, but
classifying it as a 'higher level language' and something more powerful
is incorrect....

Actually I think if you use the platform's APIs it is taking much less.
For example I think one may use Win32 API with assembly.
Also the assembly that I have primarily in mind is the one of .NET.
..NET is a CLI VM and here is a book about .NET's (CLI) VM assembly language:

http://www.amazon.com/exec/obidos/tg...glance&s=books

CLI assembly language is defined in the freely available CLI standard,
so you can view in the specification how it looks like:

http://www.ecma-international.org/pu...s/Ecma-335.htm

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #164
John Hudak wrote:
Exactly - because not every programmer is well organized to keep all the
nuances in their head, and observe them when coding. Furthermore, when
components are integrated and one component talks to another is when the
big debugging problems surface. One has to look at the
history/motivation of Ada development versus that of C/C++...Ada
certified compilers and tools strictly enforce the semantics of the
language. It has been my experience that there is a lot of variability
in C/C++ compilers in how through language semantics are adhered to.

There is no variability concerning ISO C++ features these days.
A question: With .NET facilities, when one performs an invalid operation
like accessing an array out of its bounds an exception is thrown and the
program terminates indicating what was the problem.
This is the kind of run-time safety Ada provides or is there something else?
int main()
{
using namespace System;

array<int> ^someArray= {1,2,3,4,5,6,7,8,9,0};

someArray[10]= 7;
}
C:\c>temp

Unhandled Exception: System.IndexOutOfRangeException: Index was outside
the bounds of the array.
at main()

C:\c>

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #165
Dr. Adrian Wrigley wrote:
This is is well known.

I was asking for my misconception on what *C++ was designed for* to
be dispelled.

It began as "C with classes", but this does not mean "it was designed
for" that only.

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #166
Pascal Obry wrote:
For example (if you ask):

type Table is array (1 .. 10) of Integer;

Data : Table;

for K in Data'Range loop
if Data (K) = 1 then
...
end if;
end loop;

There is no need to check K validity inside the loop as "Data (K)" is always
correct by definition (K in Data'Range). Just an example.

Pascal, this looks like Pascal.
The C++ equivalent:
#include <vector>

// ...
using namespace std;

vector<int> Data(10);

for(vector<int>::size_type i=0; i<Data.size(); ++i)
{
if (Data[i]== 1)
{
// ...
}
}
--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #167
Larry Kilgallen wrote:
Nobody has come up with something that cannot be expressed in Ada (or
in C++ for that matter). Ada code is more verbose, on the grounds that
code is read more often than it is written (or at least it should be).

Don't confuse verbose with being comprehensible. Myself that do not know
Ada, I cannot understand much when I see Ada code, apart from some
Pascal style declarations of variables, procedures and records, and this
because I have used Pascal. :-)

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #168
CTips <ct***@bestweb.net> wrote in
news:11*************@corp.supernews.com:
Peter Amey wrote:


Hans Malherbe wrote:
support efficient, real-time safe environments

Can you explain the "real-time" part?

Reading this thread, it seems to me Ada's focus is on safety rather
than efficiency.
These safety constraints also tend to limit expressiveness. Not that
safety is bad, just that it's not free.


Actually, a close reading of the thread should have made it clear
that the additional safety is indeed "free".


Free? Well, lets look at one particular issue: pointers to arbitrary
locations. In C, its a common idiom to do the following:
foo(int * p)
{
int * z;
for( i ... ) {
... p[i]...;
}
z = p;
}

...
foo( &x[lo] );
...

Now, how can *any* language check to see that p[i] is within bounds?


This is one of the unsafe idioms in C.
The fact that you can declare a formal parameter as a pointer and then
use that parameter as an array is unsafe. This can only be done
safely if you either assume the existence of meta-data in the array
to indicate the end of usable data (as in the \0 at the end of a string),
or you must pass a second parameter telling you how long the array should
be. Of course, that second parameter must be handled carefully. Improper
values in the second parameter will cause you to skip array components
or will create a bounds violation. Array bounds violations have for years
been one of the most frequent C programming errors, and a boon to
virus writers.

Ada arrays are not so closely related to pointers.
One can create an access type that "points" to an array.
type int_array is array(1..10) of integer;
type int_ptr is access int_array;

Note that int_ptr is not a pointer to an integer,
but a pointer to an array of integers.

procedure foo(p : int_ptr) is
begin
for I in p.all'range loop
... p(I)...
end loop;
end foo;

ip : int_ptr := new int_array;

foo(ip);

All this works without a problem in Ada.

Jim Rogers

Jul 23 '05 #169
Martin Dowie wrote:

[ ... ]
It's an opinion /nearly/ shared with P. J. Plauger of the ANSI-C
committee (and Dinkumware) - only I believe he quoted 100 thousand
lines as the point at which you should be using Ada. :-)


Which is utterly irrelevant to the original point, which was about
stating opinions as facts, not about who holds what opinion.

I am curious though: how do you make a meaningful comparison? If I
write something that takes only two thousand lines of SQL, it's almost
certain to take _well_ over that 100 thousand lines of Ada and might
well be closer to a million.

To me, using Ada in that situation sounds insane. Richard Reihle might
think it's the right thing to do, but I'm fairly certain that P.J.
Plaugar would disagree. I certainly don't have to think very hard to
guess at what my boss would say.

--
Later,
Jerry.

The universe is a figment of its own imagination.

Jul 23 '05 #170
Dr. Adrian Wrigley wrote:

[ ... ]
Isn't there some confusion here?

Surely the "aliasing" issue (ignored by C++ completely(?)) is largely
independent if the "reinterpret_cast"/"Unchecked_Conversion" issue?
Yes -- he started by mentioning aliasing, but mostly seemed to be
talking about type punning, so that was what I replied to. The
discussion centered around safety, which is essentially orthogonal to
aliasing.
The C++ programmer uses aliasing routinely and without thinking.
Aliasing is used frequently in C++, that much is true. IMO, the claim
that it's done "without thinking" is nothing more or less than flame
bait. I think you're capable of better.
Ada makes the aliasing possibility explicit when necessary, but
prohibits it otherwise.
Aliasing is almost certainly more common in C++, but ultimately it only
ever happens explicitly in either language. In fact, I think "explicit"
is virtually meaningless in discussing a programming language -- the
processor is not an intelligent being that makes decisions on its own
unless explicitly directed. As such, nothing in code is really
implicit. What most people call "implicit" is simply the rules of the
language doing their job. Even those who push explicitness as a virtue
rarely do things like parenthesizing a+(b*c). Even those who argue most
strongly for explicitness generally agree that this would be silly, at
least in "obvious" cases like the one above.

The "implicit" behavior I've seen Ada programmers complain about in C++
is equally codified in the rules of the language, and the fact that Ada
programmers think it's somehow implicit mostly just reflects the fact
that they don't know those rules. That's fine, but condemning the
language simply because they don't know it is much less so.
If we're talking about the "reinterpret_cast" issue, it is
essentially identical in Ada.


....and this is what actually affects safety. Aliasing mostly just makes
it more difficult to generate efficient code. Despite this, most claims
that C and/or C++ produce particularly poor code show little more than
defects in the testing.

--
Later,
Jerry.

The universe is a figment of its own imagination.

Jul 23 '05 #171
Dmitry A. Kazakov wrote:
On Tue, 08 Mar 2005 15:13:20 -0500, CTips wrote:

Dmitry A. Kazakov wrote:

On Tue, 08 Mar 2005 13:33:33 -0500, CTips wrote:
protected type Atomic_Integer is
procedure Increment;
private
Value : Integer;
end Atomic_Integer;

-- Implementation
protected body Atomic_Integer is
procedure Increment is
begin
Value := Value + 1;
end Increment;
end Atomic_Integer;

Will that generate:
L0:
lwlock temp,&Value
add temp,temp,1
stwcond temp,&Value
if( failed ) goto L0;
or will it generate something much more heavy-weight.

Ask your compiler vendor. Though it wouldn't be necessarily polling. Also
usually protected objects are not used for so utterly fine-grained mutual
exclusion/locking. Atomic integer increment is normally just a small part
of some larger (but not lengthy) operation For example, placing something
in a queue.


Umm...can be done without locking. See wait-free/lock-free algorithms.

Therefore spinning for a lock (which probably would be the implementation) will likely be less expensive than some tricky guards
attached to each and every instruction.
You *REALLY* should see what can be done with lwlock/stwcond. You'll be
suprised how cheap synchronization can be.
Note also that at such a low level
it would be very difficult if possible to maintain data consistency.
Compiler simply does not know what is related to what and will try to cope
with the worst case scenario.
So, what escapes does the language provide to let you do this? None?
Protected types in Ada are to describe this
sort of semantics. So in the end atomic integers are pretty useless, no
matter how efficient they could be implemented.


That is one reason *NOT* to learn Ada; it restricts both choices and
thinking.
Jul 23 '05 #172
Ioannis Vranos wrote:
John Hudak wrote:
Exactly - because not every programmer is well organized to keep all
the nuances in their head, and observe them when coding.
Furthermore, when components are integrated and one component talks to
another is when the big debugging problems surface. One has to look
at the history/motivation of Ada development versus that of
C/C++...Ada certified compilers and tools strictly enforce the
semantics of the language. It has been my experience that there is a
lot of variability in C/C++ compilers in how through language
semantics are adhered to.


There is no variability concerning ISO C++ features these days.


You've been lucky then... ;-)

The last time I tried to port any C++ was between VxWorks and Borland...
complete nightmare! And that wasn't so long ago...

But YMMV.

Cheers

-- Martin
Jul 23 '05 #173
Jerry Coffin wrote:
Martin Dowie wrote:

[ ... ]

It's an opinion /nearly/ shared with P. J. Plauger of the ANSI-C
committee (and Dinkumware) - only I believe he quoted 100 thousand
lines as the point at which you should be using Ada. :-)

Which is utterly irrelevant to the original point, which was about
stating opinions as facts, not about who holds what opinion.


Hey! I did add a smiley! I just thought it was an opinion from a
reputable source that tied in with the post. :-) :-)

I am curious though: how do you make a meaningful comparison? If I
write something that takes only two thousand lines of SQL, it's almost
certain to take _well_ over that 100 thousand lines of Ada and might
well be closer to a million.

To me, using Ada in that situation sounds insane. Richard Reihle might
think it's the right thing to do, but I'm fairly certain that P.J.
Plaugar would disagree.
Would I be allowed to use embedded SQL in the Ada code (GNADE)? Or a
binding to Postgres or MySQL (APQ) or similar (ODBC)?

I certainly don't have to think very hard to guess at what my boss would say.


Sorry, I don't know your boss.

Cheers

-- Martin
Jul 23 '05 #174

Ioannis Vranos <iv*@remove.this.grad.com> writes:
Pascal, this looks like Pascal.
Agreed.
The C++ equivalent:
#include <vector>

// ...
using namespace std;

vector<int> Data(10);

for(vector<int>::size_type i=0; i<Data.size(); ++i)
{
if (Data[i]== 1)


And no C++ compiler will check that Data[i] is valid. That's the point. If you
add the check explicitly no C++ compiler will be able to remove it. In the Ada
case the compiler knows lot more about the program and can decide to remove
the check if it knows that the index will never be outside the object
range. This is always the case for:

for K in Data'Range loop
... Data(k)...

Pascal.

--

--|------------------------------------------------------
--| Pascal Obry Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--| http://www.obry.org
--| "The best way to travel is by means of imagination"
--|
--| gpg --keyserver wwwkeys.pgp.net --recv-key C1082595
Jul 23 '05 #175
On Tue, 08 Mar 2005 21:51:00 -0500, CTips wrote:
Umm...can be done without locking. See wait-free/lock-free algorithms.


Honestly, I don't care. You know, I am not developing integer incrementers,
am developing software...
Therefore spinning for a lock (which probably would be the
implementation) will likely be less expensive than some tricky guards
attached to each and every instruction.


You *REALLY* should see what can be done with lwlock/stwcond. You'll be
suprised how cheap synchronization can be.
Note also that at such a low level
it would be very difficult if possible to maintain data consistency.
Compiler simply does not know what is related to what and will try to cope
with the worst case scenario.


So, what escapes does the language provide to let you do this? None?


As I said it provides protected objects, which in a real-life concurrent
application will be more efficient, far more safe and maintainable, and yet
portable as compared with your inlined assembler in C. I saw much too much
of embedded C code programmed in the style you seem to favor. The main
problem with such code, is that it's a garbage which simply does not
fulfill the requirements, including the time constraints as well.

BTW, if you are so eager to have assembly code insertions, then Ada does
have them. See ARM 13.8.
Protected types in Ada are to describe this
sort of semantics. So in the end atomic integers are pretty useless, no
matter how efficient they could be implemented.


That is one reason *NOT* to learn Ada; it restricts both choices and
thinking.


How does Ada restrict choices? As for thinking that's up to you.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Jul 23 '05 #176
On Wed, 09 Mar 2005 01:18:03 GMT, Jim Rogers wrote:
This is one of the unsafe idioms in C.
The fact that you can declare a formal parameter as a pointer and then
use that parameter as an array is unsafe.


It is also unusable with small and packed data types in which case the
array elements may have no valid machine addresses.

The bottom line: array is an interface.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Jul 23 '05 #177

CTips <ct***@bestweb.net> writes:
Will that generate:
L0:
lwlock temp,&Value
add temp,temp,1
stwcond temp,&Value
if( failed ) goto L0;
or will it generate something much more heavy-weight.


BTW, do you know a C compiler that generates such code ? Why Ada should be
different ? I think there is no way to tell compilers in any language about
somthing like that. I doubt that even the Ada "pragma Atomic" can be used to
generate such code. And as others have posted it is always possible to use
inline assembly. I don't think it is a good idea in the long term but maybe
for very specialized applications...

Pascal.

--

--|------------------------------------------------------
--| Pascal Obry Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--| http://www.obry.org
--| "The best way to travel is by means of imagination"
--|
--| gpg --keyserver wwwkeys.pgp.net --recv-key C1082595
Jul 23 '05 #178
In comp.lang.ada Jerry Coffin <jc*****@taeus.com> wrote:
rarely do things like parenthesizing a+(b*c). Even those who argue most
strongly for explicitness generally agree that this would be silly, at
least in "obvious" cases like the one above.


No, it is not silly.
It shows professionality, even when not in doubt.
There is no compelling reason to learn those many priority rules
for Ada expressions to achieve secondary bulk knowledge.

--
--Peter Hermann(49)0711-685-3611 fax3758 ic****@csv.ica.uni-stuttgart.de
--Pfaffenwaldring 27 Raum 114, D-70569 Stuttgart Uni Computeranwendungen
--http://www.csv.ica.uni-stuttgart.de/homes/ph/
--Team Ada: "C'mon people let the world begin" (Paul McCartney)
Jul 23 '05 #179
Martin Dowie wrote:
There is no variability concerning ISO C++ features these days.

You've been lucky then... ;-)

The last time I tried to port any C++ was between VxWorks and Borland...
complete nightmare! And that wasn't so long ago...

But YMMV.

The first C++ standard has been relatively recent (1998). In the
contrary Ada's has been probably around since the '80s. :-)
So it makes some sense that only the last couple of years we are getting98% conformance. Also to not forget the fact that C++ is a large language.


--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #180
Pascal Obry wrote:
The C++ equivalent:
#include <vector>

// ...
using namespace std;

vector<int> Data(10);

for(vector<int>::size_type i=0; i<Data.size(); ++i)
{
if (Data[i]== 1)

And no C++ compiler will check that Data[i] is valid. That's the point. If you
add the check explicitly no C++ compiler will be able to remove it. In the Ada
case the compiler knows lot more about the program and can decide to remove
the check if it knows that the index will never be outside the object
range. This is always the case for:

for K in Data'Range loop
... Data(k)...

Pascal.


I suppose this run-time check is something like the one provided by .NET
(mentioned in another message of mine).
ISO C++ speaking, one may use vector::at() which provides boundary
checking, however the aforementioned way is *always* 100% safe as well
as the following:
#include <vector>

// ...
using namespace std;

vector<int> Data(10);
for(vector<int>::iterator p= Data.begin(); p!=Data.end(); ++p)
{
if (*p== 1)
{
// ...
}
}

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #181

Ioannis Vranos <iv*@remove.this.grad.com> writes:
I suppose this run-time check is something like the one provided by .NET
(mentioned in another message of mine).
Yes. It seems we have some difficulties to understand each others. We were
discussing about wether the checks could be removed automatically by the
compiler if possible. The Ada type systems gives more information to the
compiler, the compiler can then make some more optimizations.

ISO C++ speaking, one may use vector::at() which provides boundary checking,
however the aforementioned way is *always* 100% safe as well as the
following:
*You* know that, but no compiler in the world knows. Static analysis is not
possible in this case.

....
for(vector<int>::iterator p= Data.begin(); p!=Data.end(); ++p)


Pascal.

--

--|------------------------------------------------------
--| Pascal Obry Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--| http://www.obry.org
--| "The best way to travel is by means of imagination"
--|
--| gpg --keyserver wwwkeys.pgp.net --recv-key C1082595
Jul 23 '05 #182
Ioannis Vranos wrote:
The first C++ standard has been relatively recent (1998). In the
contrary Ada's has been probably around since the '80s. :-)
Unless you count Stroustrup 1st edition as a standard (a la K&R) in
which case that's circa 1986! ;-)

Initial Ada draft standard are probably pre-1980 - but we as both are
ISO standards they are simply as old as their last standard, so one is
always going to be 'newer' than the other.

One nice point for Ada is that the ISO standard is available for $0, so
in one sense Ada is cheaper than C++! ;-)

So it makes some sense that only the last couple of years we are
getting >98% conformance. Also to not forget the fact that C++ is a
large language.


Yet it doesn't include so many things! ;-)

Jul 23 '05 #183
Ioannis Vranos wrote:
Pascal Obry wrote:

The C++ equivalent: for(vector<int>::size_type i=0; i<Data.size(); ++i)
{
if (Data[i]== 1)
for K in Data'Range loop
... Data(k)...

ISO C++ speaking, one may use vector::at() which provides boundary
checking, however the aforementioned way is *always* 100% safe


The loop happens to be "safe" but not by the scope and range
of i. The loops aren't equivalent, strictly speaking, because
the loop counter doesn't act as a constant.
Disciplined use of iterators/pointers/indices is not the same
thing as a constant loop index:

for (vector<int>::size_type i=0; i<Data.size(); ++i) {
if (Data.at(i)== 1)
i = 100;
}

This text is compiled without complaint as should be, because it _might_
have been the programmer's intention to set the index to some value off
bounds, and he/she _might_ not have wanted a while loop instead of a for
loop.

Some languages provide language facilities to express this difference.
A constant loop index can make some proofs easier.

Georg
Jul 23 '05 #184
Pascal Obry wrote:
Yes. It seems we have some difficulties to understand each others. We were
discussing about wether the checks could be removed automatically by the
compiler if possible. The Ada type systems gives more information to the
compiler, the compiler can then make some more optimizations.

*You* know that, but no compiler in the world knows. Static analysis is not
possible in this case.

OK, I recognise that some (probably all) Ada features provide strong
guarantees, but it is certain that they can get in the way of the
programmer.
The index being a constant, can be used in the style array(100-i)= array(i);


--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #185
Ada is not all about safety - although that is a factor in its design.
Some of it is intended to help one organize one's thoughts about the
programming problem and encourage abstraction. If one thinks in terms of
zeros and ones instead of higher level abstractions (such as
enumerations or numerical types associated with the thing they are
counting, etc.) one might find themselves "fighting the compiler". While
Ada is perfectly good at getting down to the bits and bytes and in some
ways better than C++ - (can C++ provide representation clauses on data
structures to control exactly how bits are packed and ordered?) a lot of
Ada is aimed at abstracting you away from the zeros and ones, Partly for
portability across platforms but mostly to encourage you to think about
the problem differently.

When programming in Ada, you can't think "C++" and try to do exactly
what you do in C++ only in Ada syntax. The same would be true in the
other direction. You have to work with the language rather than try to
fight what it is. Doing so, you'll likely realize the benefits intended
by the designers of the language.

MDC

Jerry Coffin wrote:

The first problem is to define what you mean by safety. Bjarne has been
fairly explicit that most safety features in C++ are intended to
prevent accidents, not intentional subversion. It's always seemed to me
that Ada has had a rather muddled idea of the "threat model", so the
language features have never been entirely aligned to a single intent.
Some parts appear intended to prevent accidents, but are quite easy to
subvert when one wishes to do so. Other parts appear to have been
designed with the intent of preventing even intentional subversion, but
fail to do so, and simply render some things quite a bit uglier than
there seems to be good reason for.


--
================================================== ====================
Marin David Condic
I work for: http://www.belcan.com/
My project is: http://www.jsf.mil/NSFrames.htm

Send Replies To: m o d c @ a m o g
c n i c . r

"'Shut up,' he explained."

-- Ring Lardner
================================================== ====================
Jul 23 '05 #186


Ioannis Vranos wrote:
[snip]
OK, I recognise that some (probably all) Ada features provide strong
guarantees, but it is certain that they can get in the way of the
programmer.
The index being a constant, can be used in the style array(100-i)=
array(i);


I think this is intended as a question. If so, the answer is "of
course". The fact that i is a constant doesn't stop you using it in
expressions or assigning it to things, it just stops you changing it.

Peter

Jul 23 '05 #187
>> Reading this thread, it seems to me Ada's focus is on safety rather
than efficiency.
These safety constraints also tend to limit expressiveness. Not that
safety is bad, just that it's not free.
Actually, a close reading of the thread should have made it clear that
the additional safety is indeed "free". Since the majority of Ada's
checks are compile time they do not impact on run-time efficiency.
.
.
.
Can you say what led you to the opposite conclusion?


I wouldn't call it a conclusion, but here goes...

Somewhere in this thread Loduvic writes:

* in Ada, loop variables (a) are constants and (b) do not exist outside
of the loop

This is safer, but limiting.
In C++ may want to declare the variable outside the loop,
break out early and use the loop variable. Let me guess: You can't
break out early in Ada, right?

* assignment is not an operator; it is an operation which does not
return a value. Thus, bugs like "if (something = 0)" cannot exist.

I like this, but it prevents chaining assignments, limiting
expressiveness slightly since chaining says "equalize" as opposed to
"assign, assign, assign".

* case statements (Ada's equivalent of a switch in C++) are required
to handle all possible cases. Thus it is impossible to forget one.
And, of course, there is no "break;" crap in Ada.

Prevents fall through.

* the type system, when used appropriately, makes it possible for the
compiler to find semantic errors in addition to just syntax errors.
For example, you can declare that Numers_Of_Apples and
Numers_Of_Oranges cannot be mixed. This is not possible with C++'s
typedef.

This is more in the C++ tradition. The programmer has choice.
In C++ you can extend the type system to achieve this and more
(someone mentioned dimensional analysis), just not with typedef.

* accessibility rules are rather complex, but they are designed to
minimise the chance of mistakes. Basically, the scope of a pointer
type must be included in the scope of the pointed-to type. This
makes many mistakes impossible, such as returning a pointer to an
object which no longer exists.

This looks like a limitation, but I'm not sure I understand correctly.
Example please!

A few other questions:

Do you have nested functions like Pascal have? Can you access local
variables? Can you pass pointers to these functions around?

Can you pass non-type parameters (like the number 3.14) to templates?

Can templates recurse?

Can you program "const correct"? Eg. if you declare a member function
as const the compiler will help you not mutate the object or call any
functions that do. Also, if you pass a parameter as a const reference,
you will not be able to mutate the object the parameter references.

Jul 23 '05 #188
Georg Bauhaus wrote:
Ioannis Vranos wrote:
Pascal Obry wrote:
for K in Data'Range loop
... Data(k)...

ISO C++ speaking, one may use vector::at() which provides boundary
checking, however the aforementioned way is *always* 100% safe


The loop happens to be "safe" but not by the scope and range
of i. The loops aren't equivalent, strictly speaking, because
the loop counter doesn't act as a constant.
Disciplined use of iterators/pointers/indices is not the same
thing as a constant loop index:

for (vector<int>::size_type i=0; i<Data.size(); ++i) {
if (Data.at(i)== 1) i = 100;
}

This text is compiled without complaint as should be, because it _might_
have been the programmer's intention to set the index to some value off
bounds, and he/she _might_ not have wanted a while loop instead of a for
loop.

Some languages provide language facilities to express this difference.
A constant loop index can make some proofs easier.


Perhaps the closest way you can get to this in C++ is

std::vector<foo_type> Data;
....
std::for_each(Data.begin(), Data.end(), DoSomething);

where "DoSomething" evaluates to a so-called "function object"
having an "operator()" accepting a (reference to) "foo_type".

Such function objects can be of dedicated classes, or can be constructed
"on the fly" (even it the latter possibility is sometimes a bit awkward
due to the lack of closures / lambda expressions in the language - btw,
does Ada have something like that?).

Falk
Jul 23 '05 #189
Peter Hermann wrote:
In comp.lang.ada Jerry Coffin <jc*****@taeus.com> wrote:
rarely do things like parenthesizing a+(b*c). Even those who argue most strongly for explicitness generally agree that this would be silly, at least in "obvious" cases like the one above.


No, it is not silly.
It shows professionality, even when not in doubt.
There is no compelling reason to learn those many priority rules
for Ada expressions to achieve secondary bulk knowledge.


Gosh, that just doesn't seem very professional to me -- after all, it's
missing the comments to remind the reader that '+' does addition, '*'
does multiplication, parentheses can be used to override the default
precedence, 'a', 'b' and 'c' are variables (and what their types are)
and so on.

To be both professional and efficient, how about if we just paste in
the entire text of the LRM before each statement? That would leave
nobody room for _any_ doubt about what the code means. Oh...well,
you're probably right: to go with, we'd better paste in the entire text
of a real dictionary, and (just in case) a complete set of books
teaching how to read English. The people you're obviously targeting as
reading the code undoubtedly need that -- after all, every word in
"Language Reference Manual" has three whole syllables!

--
Later,
Jerry.

The universe is a figment of its own imagination.

Jul 23 '05 #190
Hans Malherbe wrote:
* in Ada, loop variables (a) are constants and (b) do not exist
outside of the loop

This is safer, but limiting.
In C++ may want to declare the variable outside the loop,
break out early and use the loop variable. Let me guess: You can't
break out early in Ada, right?
Of course you can!

* case statements (Ada's equivalent of a switch in C++) are required
to handle all possible cases. Thus it is impossible to forget one.
And, of course, there is no "break;" crap in Ada.

Prevents fall through.
Call a common function/procedure

A few other questions:

Do you have nested functions like Pascal have?
Yes

Can you access local variables?
Don't understand what you mean.

Can you pass pointers to these functions around?
Yes, you can pass 'pointers' to functions around - this is being enhanced
futher in Ada2005, so that at compile time you can guarentee never to
pass a 'NULL' value.

Can you pass non-type parameters (like the number 3.14) to templates?
Yes, you can pass nearly anything.

Can you program "const correct"? Eg. if you declare a member function
as const the compiler will help you not mutate the object or call any
functions that do. Also, if you pass a parameter as a const reference,
you will not be able to mutate the object the parameter references.


Yes but Ada does not require the programmer to define what parameter
passing mechanism to use. It instead defines parameter 'modes' that
basically
indicate the 'logical flow' of the data being passed. Parameters of mode
'In'
can only be read.

Cheers

-- Martin


Jul 23 '05 #191
Falk Tannhäuser wrote:
Such function objects can be of dedicated classes, or can be constructed
"on the fly" (even it the latter possibility is sometimes a bit awkward
due to the lack of closures / lambda expressions in the language - btw,
does Ada have something like that?).


Ada 2005 adds downward closures. They have been available in GNAT/GCC
for a number of years now.
For pure Ada 95 there is a workaround using dispatching.

Is a function object similar to a downward closure?

Georg
Jul 23 '05 #192

"Hans Malherbe" <ha***********@gmail.com> writes:
This looks like a limitation, but I'm not sure I understand correctly.
Agreed. All this is somehow limiting. That's the trade off for the
safetly. But when you are used to it, this limitations are not so bad, and
quickly you can't live without them.
Example please!

A few other questions:

Do you have nested functions like Pascal have?
Yes.
Can you access local variables?
Of course yes. Otherwise what would local variables will be useful for?
Can you pass pointers to these functions around?
Around no! The rules are strict here.

This case is ok, P1 same level as PA.

<<
procedure Demo is

type PA is access procedure;

procedure P (Proc : in PA) is
begin
null;
end P;

procedure P1 is
begin
null;
end P1;

procedure P2 is
begin
P (P1'Access);
end P2;

begin
null;
end Demo;

This is not ok, P3 deeper than PA.

<<
procedure Demo is

type PA is access procedure;

procedure P (Proc : in PA) is
begin
null;
end P;

procedure P1 is
begin
null;
end P1;

procedure P2 is
procedure P3 is
begin
null;
end P3;
begin
P (P3'Access);
end P2;

begin
null;
end Demo;


Here is what GNAT reports for example:

$ gnatmake demo
gcc -c demo.adb
demo.adb:22:10: subprogram must not be deeper than access type
gnatmake: "demo.adb" compilation error

No dangling pointers.
Can you pass non-type parameters (like the number 3.14) to templates?
Yes. We can pass types, packages, procedure, functions, variables and
constants.
Can templates recurse?
Yes.
Can you program "const correct"? Eg. if you declare a member function
as const the compiler will help you not mutate the object or call any
functions that do. Also, if you pass a parameter as a const reference,
you will not be able to mutate the object the parameter references.


Not sure to understand everything. But yes, if you have:

Value : constant String := "whatever";

It will never be able to mutate Value.

Pascal.

--

--|------------------------------------------------------
--| Pascal Obry Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--| http://www.obry.org
--| "The best way to travel is by means of imagination"
--|
--| gpg --keyserver wwwkeys.pgp.net --recv-key C1082595
Jul 23 '05 #193
On 09 Mar 2005 15:55:38 +0100, Pascal Obry <pa****@obry.org> wrote:
Can you program "const correct"? Eg. if you declare a member function
as const the compiler will help you not mutate the object or call any
functions that do. Also, if you pass a parameter as a const reference,
you will not be able to mutate the object the parameter references.

Ada supports the first functionality - not modifying the parameter itself
(since it is of mode "in" or "access"). This is for all parameters to
functions (as distinct from procedures).

Ada does not support the idea of a const reference, though: if the
function parameter is of an access type, or mode "access", the reference
to the object cannot be changed, but the contents of the referenced object
can be.
Jul 23 '05 #194
Hans Malherbe wrote:
Can you program "const correct"? Eg. if you declare a member function
as const the compiler will help you not mutate the object or call any
functions that do. Also, if you pass a parameter as a const reference,
you will not be able to mutate the object the parameter references.


well, this one seems problematic to non-C++ users, and especially to
Ada users, so i will explain a bit further:

let's have a C++ class:

class T
{
public:
void dummy() const;
void dummy2();

protected:
int field;
};

T myObject;
myObject.dummy(); // here, myObject.field will not change
// because dummy is const
myObject.dummy2(); // here, myObject.field may change...

in C++, dummy() should not be able to call dummy2() since dummy2() is
not const, so it may change the state of the object, which is not
allowed because dummy() is const.
let's see it the Ada way: we dont use the dotted notation. instead we
explicitly pass the oject as a parameter, specifying a mode which
tells what we want to do with the object:

type T is tagged record
Field : Integer;
end record;

procedure Dummy( This : in T );
procedure Dummy_2( This : in out T );

My_Object : T;
Dummy( My_Object );
Dummy2( My_Object );

since the "This" parameter in "Dummy" is declared with mode "in", we
cant assign a value to any field of "This": "This" will then be
constant. also, "Dummy" cannot call "Dummy_2" passing it its "This"
parameter: "Dummy_2" requires to be able to assign to "This", but
"This" is constant in "Dummy".

so the answer is : yes, we can enforce constness in Ada. we can even
express more since we have many parameter passing modes available:
- with in mode, we cant assign to the parameter
- with out mode, we should only assign a value to the parameter (not
rely on its initial value)(this one is missing in C++)
- with in out mode, we may read and assign the parameter
- with access mode, well, this is a reference passing mode (i find it
hard to explain the difference with the other modes, someone else may
take up on this one)

--
rien
Jul 23 '05 #195
Hans Malherbe wrote:
* in Ada, loop variables (a) are constants and (b) do not exist outside
of the loop

This is safer, but limiting.
In C++ may want to declare the variable outside the loop,
break out early and use the loop variable. Let me guess: You can't
break out early in Ada, right?
No, there is all kind of loop control,

loop_statement ::=
[loop_statement_identifier:]
[iteration_scheme] loop
sequence_of_statements
end loop [loop_identifier];

Inside the loop (sequence_of_statements) you can break out
using for example

exit [loop_name] [when condition];

(And you can start a new nested block inside a loop with a package in it
with a task type in it etc. if that makes sense in a program.)
* case statements (Ada's equivalent of a switch in C++) are required
to handle all possible cases. Thus it is impossible to forget one.
And, of course, there is no "break;" crap in Ada.

Prevents fall through.
Yes, no fall through in "case ... end case", which is why case and
switch are not exactly equivalent. There is nice grouping of cases.
You can write fall through switches though, when necessary,
or desirable, only they won't look like a case distinction.

A few other questions:

Do you have nested functions like Pascal have? Can you access local
variables? Can you pass pointers to these functions around?
Yes. There are restrictions on pointers to locally allocated objects used
in an outer scope. The restricted items include local functions,
e.g. there are no full upward closures.

Can you pass non-type parameters (like the number 3.14) to templates?
Yes, formal template parameters include floating point types and values.
Can templates recurse?
No. (Though you can mix recursive subprograms, nesting, and template
instantiation.)

I think that it is *this* fact ("recursive templates"), the "programmability
of a C++ compiler via templates", that allows a C++ programmer to do many
things that otherwise aren't available in the language.
For example, the
Can_Copy, Can_This, Can_That
idiom is built into Ada, Eiffel, etc. via constraint genericity,
and so doesn't require a "template computing compiler" for constraining.
OTOH, this is a limitation, even though there is a richt set of
"parameter things" in Ada, including types, interface types, values,
subprograms, and packages (templates parameterized by other templates).

Can you program "const correct"? Eg. if you declare a member function
as const the compiler will help you not mutate the object or call any
functions that do.
The const-mechanics are slightly different.
In order to preclude modifications of the object, use parameter modes,
see below.
The analog of the this pointer is passed to a primitive operation,
i.e. a member function. Ada 2005 adds dotted notation in addition to passing
a this-like value. Now,
if a subprogram's parameter modes disallow modifying the "this parameter",
you can't modify the object's state in the subprogram body
(without trickery that is).
Also, if you pass a parameter as a const reference,
you will not be able to mutate the object the parameter references.


The passing modes are, in, in out, and out.
They are logical and indeed separate from direct or indirect access to
the values at the processor instruction level. The compiler usually
chooses what it thinks is best when the language leaves this open.

Georg
Jul 23 '05 #196

Georg Bauhaus <ba*****@futureapps.de> writes:
Can templates recurse?


No. (Though you can mix recursive subprograms, nesting, and template
instantiation.)


Hum, since you answered "no" and I answered "yes" it seems there is something
about "templates recurse" that I did not understand. In short what is a
recursive template in C++ ?

Thanks,
Pascal.

--

--|------------------------------------------------------
--| Pascal Obry Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--| http://www.obry.org
--| "The best way to travel is by means of imagination"
--|
--| gpg --keyserver wwwkeys.pgp.net --recv-key C1082595
Jul 23 '05 #197
Ed Falis wrote:
On 09 Mar 2005 15:55:38 +0100, Pascal Obry <pa****@obry.org> wrote:
Can you program "const correct"?
Ada does not support the idea of a const reference, though: if the
function parameter is of an access type, or mode "access", the
reference to the object cannot be changed, but the contents of the
referenced object can be.


Although with "access constant" types, a similar idea is supported:

type R is record
v: Natural;
end record;

type CP is access constant R;

procedure proc(t: CP) is
begin
t.v := 4;
end proc;

$ compiling...

23. t.v := 4;
| left hand side of assignment must be a variable


Georg
Jul 23 '05 #198

Hans Malherbe wrote:
Somewhere in this thread Loduvic writes:

* in Ada, loop variables (a) are constants and (b) do not exist outside of the loop

This is safer, but limiting.
In C++ may want to declare the variable outside the loop,
break out early and use the loop variable. Let me guess: You can't
break out early in Ada, right?
I see your problem, and I think I see where you have been
misled. Ada provides three looping forms. Only one, the "for"
loop, uses an automatically created local loop variable.

Ada does allow you to break out of a loop early. In fact,
one of the looping forms normally depends on that ability.

The looping forms in Ada are:

Simple loop ->

loop
some actions;
end loop;

While loop ->

while condition loop
some actions;
end loop;

For loop ->

for I in some_range loop
some actions;
end loop;

The simple loop will always be an infinite loop unless
you break out early. The Ada reserved word used to
break out of a loop is "exit". In Ada "exit" does not
exit the program, only the enlcosing loop.

The Ada exit command is commonly used in response to
some condition:

if condition then
exit;
end if;

This usage is so common that Ada provides a short-hand
syntax to achieve the same ends:

exit when condition;

The exit command can be used in any of the loop forms.

The simple loop is often used to provide a loop with the
conditional test in the middle or at the bottom of the loop.
The conditional test is the condition controlling the exit
command.

The while loop works just like you would expect in many
other languages.

The for loop is somewhat like a foreach loop in C and C++.
It iterates through a discrete range of values. The loop
control variable in the for loop is local to the loop
and is read-only within the loop body.

You should probably choose either the simple loop or the
while loop if you want to use the value of a loop control
variable outside the body of the loop. The only way to use
that value outside the body of a "for" loop is to copy the
value to a variable having a scope outside the loop.

* assignment is not an operator; it is an operation which does not
return a value. Thus, bugs like "if (something = 0)" cannot exist.

I like this, but it prevents chaining assignments, limiting
expressiveness slightly since chaining says "equalize" as opposed to
"assign, assign, assign".
You have that correct.

* case statements (Ada's equivalent of a switch in C++) are required
to handle all possible cases. Thus it is impossible to forget one.
And, of course, there is no "break;" crap in Ada.

Prevents fall through.
The Ada case statement is a little more useful than might appear
from the description above.

The general form of the Ada case statement is:

case discrete_value is
when value_list =>
... some set of statements ...
when others =>
... some set of statements ...
end case;

The value_list can be in the form of:
* a single value (i.e. 255)

* a range of values (i.e. 1..5)

* a discontinuous set of values (i.e. 1 | 3 | 5 | 17)

The Ada case statement requires that there be a when clause
for every possible value of the type being tested. This works
because Ada also allows you to define your own discrete types
and subtypes, including their valid value ranges.

subtype Menu_Options is character range 'a'..'c';

option : Menu_Options;

case option in
when 'a' =>
do_action_a;
when 'b' =>
do_action_b;
when 'c' =>
do_action_c;
end case;

If, in the example above, I left out the "when 'c' =>"
part the compiler will issue an error.

The "when others =>" option is equivalent to the "default"
option in C and C++.

* the type system, when used appropriately, makes it possible for the
compiler to find semantic errors in addition to just syntax errors.
For example, you can declare that Numers_Of_Apples and
Numers_Of_Oranges cannot be mixed. This is not possible with C++'s
typedef.

This is more in the C++ tradition. The programmer has choice.
In C++ you can extend the type system to achieve this and more
(someone mentioned dimensional analysis), just not with typedef.

True. C++ provides strong type separation through the use of
classes.
* accessibility rules are rather complex, but they are designed to
minimise the chance of mistakes. Basically, the scope of a pointer
type must be included in the scope of the pointed-to type. This
makes many mistakes impossible, such as returning a pointer to an
object which no longer exists.

This looks like a limitation, but I'm not sure I understand correctly. Example please!
Ada does not provide any generic pointer type equivalent to void*.
You must define each pointer type you want to use. Objects of that
pointer type must be placed within the scope of the definition of
their type. Outside that scope the type does not exist.

This rule does not prevent all attempts to deallocate a null pointer.
Null pointers can be found in any scope and are not only found
when a type goes out of scope.

A few other questions:

Do you have nested functions like Pascal have? Can you access local
variables? Can you pass pointers to these functions around?
Yes, Ada does allow nested functions, procedures, tasks, and
even packages. A function can access any local visible local
variable. Variables declared in an enclosing scope are visible
within the nested function.

You can create pointers to functions. This is yet another type
of pointer you can create. Pointers to nested functions are
only valid within the enclosing scope of the nested function.

Can you pass non-type parameters (like the number 3.14) to templates?
Yes, Ada generics allow values to be passed, including floating
point values. The generic formal parameter for the value specifies
what type the value can be.

Can templates recurse?

Once a generic is instantiated it behaves like any other
compilation unit. Recursion is allowed within generic
subprograms.
Can you program "const correct"? Eg. if you declare a member function
as const the compiler will help you not mutate the object or call any
functions that do. Also, if you pass a parameter as a const reference, you will not be able to mutate the object the parameter references.


Ada syntax for defining what most other languages call classes is a
bit unique. Ada does not use the term "class" like other languages.
The Ada package is used for encapsulation and namespace. A package
specification contains an implicit public part and an explicit
private part. A package may contain more than one type definiton.

Extensible types in Ada are called tagged types. They were introduced
in Ada 95 as an extension of the Ada 83 record syntax.

Ada does not use the dot notation for calling member methods for
tagged types.

For example, if you define a dog class in C++ or Java, and provide
a feed() member function, you call the function as:

dog d;

d.feed();

In Ada you can create a dog tagged type, and in the same package
specification you can define a procedure to feed the dog.
The procedure specification would look like:

procedure feed(The_Dog : out dog);

The procedure would be called as:

d : dog;

feed(d);

or, using named notation:

feed(The_Dog => d);

The procedure specification is the key to "const correctness".
Procedure parameters have a passing mode. Three options are
possible for the passing mode:

IN --- Parameter is treated as a const (read-only) value
within the procedure or function. Function parameters
can only be IN mode.
OUT --- Parameter is both readable and writeable within the
procedure, but there is not guarantee of an intial
value for the parameter
IN OUT - Parameter is both readable and writeable within
the procedure. Parameter retains the value passed
in from the actual parameter.

Jim Rogers

Jul 23 '05 #199
On Wed, 09 Mar 2005 16:55:38 +0100, Georg Bauhaus <ba*****@futureapps.de>
wrote:
Although with "access constant" types, a similar idea is supported:

Right, I remembered that construct after the fact.
Jul 23 '05 #200

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

20
by: Mediocre Person | last post by:
Well, after years of teaching grade 12 students c++, I've decided to make a switch to Python. Why? * interactive mode for learning * less fussing with edit - compile - link - run - debug -...
14
by: Gabriel Zachmann | last post by:
This post is not strictly Python-specific, still I would like to learn other university teachers' opinion. Currently, I'm teaching "introduction to OO programming" at the undergrad level. My...
3
by: andy_irl | last post by:
Hi there I have been asked to teach HTML to a group in our local village community. It is nothing too serious, just a community development grant aided scheme. It will be a 10 week course of two...
12
by: Pierre Senellart | last post by:
I am going to teach a basic Web design course (fundamentals of HTML/CSS, plus some basic client-side (JavaScript) and server-side (PHP, perhaps XSLT) scripting). Most of the students do not have...
16
by: msnews.microsoft.com | last post by:
I am teaching C# to my 11 year old child. One challenge is that all the C# books I own and that I have seen in bookstores are full of language that is not easily comprehended by a student at that...
24
by: Richard Aubin | last post by:
I'm really new to vb.net programming and programming in general. I would like to teach myself on how to program effectively and I have the financial and time resources to do so. Can I anyone...
0
by: e.expelliarmus | last post by:
check this out buddies. kool website for: * hacking and anti hacking tricks * anti hackng tricks. * registry tweaks * orkut tricks * small virus * computer tricks and loads of different...
1
by: JosAH | last post by:
Greetings, Introduction This week's tip describes a few old tricks that are almost forgotten by most people around here. Sometimes there's no need for these tricks anymore because processors...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.