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

  • Thread starter Turamnvia Suouriviaskimatta
  • Start date
I

Ioannis Vranos

Pascal said:
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== 1)



And no C++ compiler will check that Data 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)
{
// ...
}
}
 
P

Pascal Obry

Ioannis Vranos said:
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
 
M

Martin Dowie

Ioannis said:
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! ;-)
 
G

Georg Bauhaus

Ioannis said:
Pascal Obry wrote:
The C++ equivalent:
for(vector<int>::size_type i=0; i<Data.size(); ++i)
{
if (Data== 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
 
I

Ioannis Vranos

Pascal said:
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);
 
M

Marin David Condic

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 said:
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
======================================================================
 
P

Peter Amey

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
 
H

Hans Malherbe

Reading this thread, it seems to me Ada's focus is on safety rather
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.
 
?

=?ISO-8859-1?Q?Falk_Tannh=E4user?=

Georg said:
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
 
J

Jerry Coffin

Peter said:
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!
 
M

Martin Dowie

Hans said:
* 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
 
P

Pascal Obry

Hans Malherbe said:
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
 
G

Georg Bauhaus

Falk said:
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
 
E

Ed Falis

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.
 
A

Adrien Plisson

Hans said:
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)
 
G

Georg Bauhaus

Hans said:
* 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
 
P

Pascal Obry

Georg Bauhaus said:
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
 
G

Georg Bauhaus

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;
|
Georg
 
J

jimmaureenrogers

Hans said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,206
Messages
2,571,069
Members
47,674
Latest member
scazeho

Latest Threads

Top