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

  • Thread starter Turamnvia Suouriviaskimatta
  • Start date
I

Ioannis Vranos

REH said:
I would love have named parameters too. That way I would not have to
"agonize" over the "priority" of my default parameters (i.e., if there are
10 and I have to change the 10th from its default, I have to define the
first 9).


The many parameters passed by reference to be modified is an outdated C
style.


*Today* one may use a std::pair or a combination of std::pairs for
return values.

E.g.

//Returns 2 values
pair<int, int> somefunc();


// Returns 4 values
pair<pair<int, int>, pair<int, int> >somefunc();

// Returns 3 values
pair<pair<int, int>, int>somefunc();


Also this gets more syntactic sugar with the upcoming TR1 standard
library extension and more particularly with "Tuple types".


Here are the proposals that have been accepted for the upcoming TR1:

http://www.open-std.org/jtc1/sc22/wg21/docs/library_technical_report.html


Personally although more sugar-rich (and still built with the current
C++ facilities, which demonstrates the power and expressiveness of the
language), I am not sure we needed Tuple types, since std::pair does the
job. :)

I suppose tuple types continue to be convenient for something like 10
return values, since it is just a returned object with the contained
values, but I think returning (or passing) so many values means
something is wrong. :)
 
R

REH

Ioannis Vranos said:
I do not know what you mean exactly by that, however one can define his
own types rather than having everything as built-in.

Ada allows you to define a primative type (int, etc.) that is "distinct"
from others. This is nice for overload resolution, etc.
C++ provides general purpose facilities with which one can build his own
special purpose libraries, rather than providing special purpose
facilities as built in.
I know, but being about to write "is new integer" is a lot simplier than
creating a class just to create a "unique" integer type. Plus. since it is
a unique type I can define its exact size in bits which make portabililty
easier:

type Byte is new integer range 0 .. 16#ff#;
for Byte'size use 8;
May I assume that packages are a form of precompiled dynamic-link
libraries, like dlls in Windows?
No, they are compilation construct (and can be define in a hierarchy). The
are kind of like namespaces. If you ever used Borland's Turbo Pascal, they
are like units. They make it easy to separate interface and implementation.
Even inlines and generic bodys go in the body package, and not the
specification package, and can be used in a library without needing the
source present to be used. They also allow for the creation of an
elaboration (static construction) order between packages to be defined.
 
I

Ioannis Vranos

Ioannis said:
Personally although more sugar-rich (and still built with the current
C++ facilities, which demonstrates the power and expressiveness of the
language), I am not sure we needed Tuple types, since std::pair does the
job. :)

I suppose tuple types continue to be convenient for something like 10
return values, since it is just a returned object with the contained
values, but I think returning (or passing) so many values means
something is wrong. :)


Since tuple types are to be used for more things than only returned and
passed values, I recall the above. :)
 
D

Dr. Adrian Wrigley

"Dr. Adrian Wrigley" <[email protected]> skrev i en
meddelelse


This can be implemented mostly with templates.

the evidence I find is that these Ada features meet programmers'
needs (because they are widely used), yet the nearest equivalent
with templates is almost never used (I have never seen examples).
I don't think new template classes match the utility of new
types and subranges in practical terms (but I'm prepared to
be shown wrong!).

How, for example, do you create a new 2-D array indexed by
enumeration sub-ranges?

For example, what is the templated, range-checked equivalent of:
------------------------------------------
generic
type Index_T is (<>);
type Intensity_T is digits <>;
package CrossBright_P is
type CrossIntensity_T is array (Index_T, Index_T) of Intensity_T;
-- more subprograms here
end CrossBright_P;

type EMSpectrum_T is (Gamma_Ray, X_Ray, Ultra_Violet, Visible, Infra_Red, Microwave, Radio_Wave);
type Intensity_T is digits 6 range 0.0 .. 10_000.0;

type CrossSpectrumIntensity_T is array (EMSpectrum_T, EMSpectrum_T) of Intensity_T;

package MyCrossBright is new CrossBright_P (EMSpectrum_T, Intensity_T);

CrossIntensity : MyCrossBright.CrossIntensity_T := (others => (others => Intensity_T'First));
--------------------------------------------------------------
How would you do that without "compiling on the fly"?

same way as in Ada!
This will be part of the next standard, I hope. Still i do not believe it to
be esential for use.

It is sometimes handy to use the C preprocessor for local functions
Why? What is the purpose - if not to restrict portability?

To get access to externally defined data storage!!
For example, hardware devices, network data representation,
interfacing to machine code etc.

....
I doubt that this should be part of the standard. What is needed is
specification of low-level features in e.g. multiprocessor environments.

I think portable concurrent or distributed programming is a paradigm
poorly (non) supported by C++. The current situation is a mess.
Most of these "implementation defined" parts are there for portability. To
many definitions will make it more difficult to port C++ to other platforms.

But at least any difficulty is addressed once per platform,
rather than once for each program!
I do not see the purpose of the out-parameter. Why not simply return the
value(s)?

How do you return multiple values?
As for named parameter associations, these can again be implemented in a
library.

Again, they are widely used in Ada code, but very rarely in C++.
I found the library implementation kludgey.
For C++ portability from C was (and is) an important issue. Thus there is no
question about remocing e.g. pointer-arithmetic and decaying of arrays to
pointers. This simply can not happen. Also some of these features are needed
for an efficient implementation of low-level classes (e.g. std::vector).
What you can do is not use these features. And it is just a matter of
education to routinely use e.g. std::vector< t > and std::string instead of
arrays and char pointers.

You can't routinely use only the new features, because library
code mainly uses the old features. (most libraries are supplied
via C-style header files)
There are some bad decisions in the type system - specifically i hate the
automatic conversions from double to integral value. But again - this is
something you have to live with.

(only if you have to use C++!)
Right. The template stuff could possibly have been more elegant.

I am not sure i follow you here. In what way do you want portability? Are
you thinking of e.g. portability between an X-windows system and Windows? Or
portability of lower-level constructs such as multithreading or networking?
I wonder how Ada does this stuff.

portability for different type sizes (eg pointer widths, char signedness,
basic type ranges, data alignment)
I thought Ada supported generic programming. Isn't it then just a question
of creating a library?

it's a nuisance to have to define a suitable hashing function for
each type, particularly one you are several levels into a generic nesting!
The hashing function might need to be passed in at the top and
built in stages at each level. Not nice. (is there an alternative?)
 
R

REH

Ioannis Vranos said:
The many parameters passed by reference to be modified is an outdated C
style.
That's not what I mean. I mean I have a function foo that takes many
parameters. I can think of nothing beyond a contrived example:

void foo(int a= 1, int b = 2, int c = 3);

I usually try and determine which will change most often, and make that the
first one, and on down the line. The is because if I need to define
parameter c in a call to foo, I need to define a and b also. In Ada I can
just say:

foo(c => 5);

I had one instance where I had many complex objects that took a lot of
constructor parameters. I ended up putting the parameters in related
groups, and making each group a struct, each with its own set of defaults so
I would only have to define them if I cared about a particular group. I'm
sure there is probably a better design. I hope that was clear.
 
R

REH

Dr. Adrian Wrigley said:
It is sometimes handy to use the C preprocessor for local functions
That would not work in the example above, i.e., for use as the operation
given to STL algorithms. Besides, inline is better for "quick" functions
than the preprocessor.

The closest thing I've seen in C++ is a locally define class with operator
() defines, but:

1) All the compilers I have used usually choke on this, especially with
optimization turned on (I don't know what the standard actually says about
doing this, though).

2) To access variables from "outer scopes" you would have to send them in
through the constructor.
 
R

Robert A Duff

Jerry Coffin said:
Robert A Duff wrote:

[ ... ]
If you really want to know about these languages that are being
discussed (Ada and C++) nothing beats reading a textbook or two.

Much as I hate to further my (undoubtedy bad) reputation for being
disagreeable, I still have to disagree.

If you follow-up the reading with some real use, it beats reading alone
by a wide margin, at least IME.

But I agree with that! Your reputation as disagreeable is ruined. ;-)

On the other hand, if you do "real use" by itself, you're liable to fall
into the trap of thinking that "what my compiler happens to do" is equal
to "the language definition".

- Bob
 
R

Robert A Duff

CTips said:
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?

Dmitry showed how to *use* an arena allocator. You (CTips) seem to be
asking how to write the code of the allocator itself.

Yes, it's ``a "class" that can invoke sbrk (or whatever)''.
That is, the code for Allocate and Deallocate are written by the
programmer to do whatever is necessary, and are called automatically by
"new" and "Unchecked_Deallocation". (Unchecked_Deallocation is like
free.) The "arena" allocator can of course do what it likes -- allocate
from a blob of memory, or allocate small pieces out of large chunks,
or request more memory from the OS (if there *is* an OS), etc.

I'm a little confused about what you (CTips) are asking.
Maybe you could clarify a bit...
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.

It will generate something much more heavy-weight, but portable,
in most Ada compilers. If you want access to machine instructions,
you use machine code inserts, but of course you then lose portability.

I don't know of any Ada compiler that's smart enough to compile the
above into the most efficient code on machines that *do* have those
atomic instructions.

I thought this discussion was about C++ vs. Ada. Both allow
machine-code inserts. And (of course) machine-code is not portable.
I don't see any difference there.

- Bob
 
W

Wes Groleau

In order to suppress all checks, with Ada we can use Pragma Suppress()
yet with C++ we have to write a totally different new code when you
don't want anymore checks (if using C++ "try .. catch" constructs).

And in the pragma, you can be explicit about which checks to suppress,
which entity to suppress them on, and what scope to do it in.


--
Wes Groleau

Trying to be happy is like trying to build a machine for which
the only specification is that it should run noiselessly.
-- unknown
 
W

Wes Groleau

Jerry said:
Thinking of Java as a safer C++ betrays misundertanding of one (or
probably) both languages. Comparisons between Ada and C++ are at least

A misunderstanding shared by the inventors of Java?

I watched a 30-minute video tape in which they said
they kept having this and that problem, so they invented
a language that would not have those problems. One of them
held up for the camera a copy of some C++ book with lots of
things lined out and said something like, "Basically, we just
eliminated all this unsafe stuff."

--
Wes Groleau

There are some ideas so wrong that only a
very intelligent person could believe in them.
-- George Orwell
 
W

Wes Groleau

Pascal said:
That's not a misunderstanding. That's how Sun has described Java. They started
from C++ and have removed many unsafe features. They eventually stop the
process at some point and this has given birth to Java. That's history.

Although in at least one point they removed something that
Ada had already proved is not necessarily unsafe: operator
overloading. As a result, Java programmers either have to
give up both object-orienting and abstraction or use crap like

A.Multiply(2).Divide(B.negative().add(sqrt(B.squared().add(A.mult(2).mult(C)))

for things that are conceptually numeric.

--
Wes Groleau

If you put garbage in a computer nothing comes out but garbage.
But this garbage, having passed through a very expensive machine,
is somehow ennobled and none dare criticize it.
 
W

Wes Groleau

Jerry said:
First of all, work on ARPAnet started out around the mid-1960's, but it
only became available to most of the public around the early 1990's or
so. Had development been delayed for 20 years or so until Ada compilers
were available, we'd be waiting another five years or so before it
became available to most of its current users.

And if development been delayed until C compilers were available?


--
Wes Groleau
"Grant me the serenity to accept those I cannot change;
the courage to change the one I can;
and the wisdom to know it's me."
-- unknown
 
W

Wes Groleau

Alberto said:
As many people on this thread noticed, it was only a (bad?) joke. I
simply wanted to remark that I was somewhat tired of reading the same
story of Ada L. when some innocent soul dared to write "ADA" :)

From another newsgroup: "How can you expect to program in perl
if you can't even spell it?"

(not the exact words)
 
W

Wes Groleau

Dmitry said:
No, the difference is that the compiler *statically* knows that both I and
J will be in the bounds at run-time. There is no way (except for dirty
tricks with casting) how they might become out of the bounds. Therefore the
compiler can safely omit any checks.

Actually, the compiler will not allow any casting into
loop control variables. And if they were not loop control
variables, the compiler will add checks anywhere that can
be reached from code that has done such a conversion.

--
Wes Groleau

After the christening of his baby brother in church, Jason sobbed
all the way home in the back seat of the car. His father asked him
three times what was wrong. Finally, the boy replied, "That preacher
said he wanted us brought up in a Christian home, and I wanted to
stay with you guys."
 
L

Ludovic Brenta

Jerry Coffin said:
Short of using things like casts that are designed specifically to
_prevent_ the compiler from giving warnings (and which have their
counterparts in Ada) what practices on the "wrong side" do you see
that a C++ compiler can't warn about?

Aliasing?
 
L

Ludovic Brenta

Jerry Coffin said:
Perhaps not -- but the strong implication that C++ was NOT used in
such systems, seems to leave only two possible conclusions: the
person who made the implication was either ignorant or lying.

I prefer to think this WAS big news, meaning the implication was
simply an honest mistake rather than an outright lie, or the result
of such a shallow view as to ignore the majority of the system.

Many ATC systems have a GUI which runs on top of X and Motif.
Toolkits such as the one you referred to are designed to avoid C or
C++ programming when creating the GUI. Instead, the GUI is generated
from point-and-click interfaces. That's fine by me.

Any tool that helps avoid mistakes or catch mistakes early is IMHO
good. Eventually, all tools end up generating machine code anyway.
It's just that Ada is better than C++ for safety-critical software.
Code generators can also help, even if they generate unreadable C or
C++ or machine code.

Even in Barco's avionics displays, part of the software is in C, but
generated from a GUI code generator. Our customers are usually
responsible for this (since they define the graphical appearance of
the display), so we don't worry too much about that. But buffer
overflows have been known to happen in the generated code during
testing :)

I maintain that most of Eurocontrol's software is written in Ada. I
think there was an old issue of the Ada User Journal detailing this.
I'm not sure about the GUI however; how much of it is generated I
don't know.
 
M

Martin Dowie

Ok, what about this paper:
http://www.praxis-his.com/pdfs/c_by_c_better_cheaper.pdf

In particular the company audited by the UK MoD on the 3rd page showed
interesting results. I work for the company audited and I'm sure the
audit is post-1995 by some margin (when I was no longer working there),
and by your own argument, by 1990 the compilers were pretty close to
standard C, yet this study still found a 10*defect rate in C than in
Ada... and a 100* defect rate compared to SPARK...

Yet, this sort of report seems all to common to me. Every language since
'C' has had at least 1 report that shows how brilliant it is at compared
to 'C', yet 'C' is still the most widely spread language. Why?

I think we perhaps need a psychologists view rather than looking at
language differences. Are humans 'hooked' on tracking down /really/
tricky null pointer dereference problems? Is it really just a fight for
'silver back status' coz 'my programs compile to 1 long word less than
yours'?...

Cheers

-- Martin
 
I

Ioannis Vranos

REH said:
Ada allows you to define a primative type (int, etc.) that is "distinct"
from others. This is nice for overload resolution, etc.

I know, but being about to write "is new integer" is a lot simplier than
creating a class just to create a "unique" integer type. Plus. since it is
a unique type I can define its exact size in bits which make portabililty
easier:

type Byte is new integer range 0 .. 16#ff#;
for Byte'size use 8;


I am pretty sure one can write a library that can enable just that.


Now that I am thinking of it, there are some, and let's begin from Boost:


http://www.boost.org/libs/integer/integer.htm


#include <boost/integer.hpp>


int main()
{
using namespace boost;

int_t<24>::least my_var;
}



with "least" being the smallest built-in type that supports the given
bit count.



You see, that's easy. :) Just "plug in" Boost.


I am sure there are other libraries too.
 
J

Jerry Coffin

Robert A Duff wrote:

[ ... ]
But I agree with that! Your reputation as disagreeable is ruined.
;-)

Pardon my being blunt, but Damn! The one thing I was good at is ruined!
On the other hand, if you do "real use" by itself, you're liable to
fall into the trap of thinking that "what my compiler happens to do"
is equal to "the language definition".

This, unfortunately, is all too true.
 

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,202
Messages
2,571,058
Members
47,668
Latest member
SamiraShac

Latest Threads

Top