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

  • Thread starter Turamnvia Suouriviaskimatta
  • Start date
I

Ioannis Vranos

Georg said:
µC++ adds concurrency support to the C++ type system, at a somewhat
lower level of abstraction than Ada.


Concurrency is a hot issue, currently considered system-specific in C++.
It will be included in C++0x (I hope the right choices will be made).

There is also OpenMP of course (http://www.openmp.org).

Still, µC+++ reimports the weaknesses of the precursor languages.
Sad, but successful because of mass momentum.


I keep hearing about this µC++, may you provide a relevant link? I
couldn't find anything in google, is the first character a Greek
character? It appears as the Greek character 'm' in my screen.
 
G

Georg Bauhaus

Jerry said:
Some areas are somewhat more questionable -- calling a class a "tagged
record" is clearly a mistake, but it's open to question whether it
should be classified under poor expression of the concept, or just
general idiocy.

http://groups-beta.google.com/group...p:comp.lang.ada+author:dewar#f6536ae8243e253c

class type T is ...

instead of

type T is tagged ...


In C++ you can throw an arbitrary type of object with an arbitrary
value.

How well does this style of passing information work across thread
boundaries? (Not debating the usefulness of the mechanism. Although
I think it deserves to be separated from exception handling.)

Georg
 
L

Larry Kilgallen

Some of the cited cases provide checks that are free in terms of
run-time, but run-time is hardly the major cost in most software.

Really ?

Even programs I write for my own personal use are run _many_ more times
than they are compiled. Personally, I often spend compile time thinking
some more about the problem, sometimes to good advantage :)
Just for one obvious example, Ada doesn't provide an easy way to
express/do most of the things one can do with the C or C++
preprocessor.

It does not provide a preprocessor, for safety reasons.

But what programming step (as distinguished from construction trick)
can only be performed from a preprocessor ?
Some areas are somewhat more questionable -- calling a class a "tagged
record" is clearly a mistake, but it's open to question whether it
should be classified under poor expression of the concept, or just
general idiocy.

I see no mistake. Is it possible your background in Pascal is inadequate
and overwhelmed by your background in C* languages.
 
R

Robert A Duff

2. Your example did not use "straight" C++. Instead, you relied
on the Vector template.

I'm not sure why that's not "straight". That feature is a standard part
of C++, so it seems fair to use it in an example.

What's not fair is to claim that it's the same thing as a fixed-length
array, or to claim that map is equivalent to vector.
Regarding number 3, I wish Ada had a good model of multiple
inheritance.

Ada 2005 has interfaces, which were inspired by Java.

- Bob
 
I

Ioannis Vranos

Dr. Adrian Wrigley said:
And you can do really handy stuff passing arrays not indexed from 0,
and accessing the attributes:

-- No particular purpose but to demo
type MyString is array (Integer range <>) of Integer;

procedure UpdateString (Blob : in out MyString; K : Integer) is
begin

if Blob'Length = 0 then
return;
elsif Blob'Length = 1 then
Blob (Blob'First) := Blob (Blob'First) + K;
return;
else
UpdateString (Blob (Blob'First .. Blob'First+Blob'Length/2-1), 19);
UpdateString (Blob (Blob'First+Blob'Length/2 .. Blob'Last), 27);
return;
end if;

end UpdateString;
...
UpdateString (Fred (10 .. 19), 0);


If you provide some explanations, I will give you the C++ equivalent.

What does this mean?

Blob : in out MyString
 
M

Matthew Heaney

Jerry said:
char[] and wchar_t[] are arrays, not strings.

Well, that's true of Ada's String and Wide_String.

C++ really only has one
string type: std::basic_string. std::string and std::wstring are not
types of their own at all, but simply typedefs as:

typedef std::basic_string<char> string;
typedef std::basic_string<wchar_t> wstring;

That's more or less what type Unbounded_String is, too.

There appears to be a difference in terminology. I and every other
developer I know refers to type const char* as a string. (For example,
H&S Ch. 13 is titled "String Processing.")

In any event, that's probably how the OP was using the term when he
said "Ada has 5 string types." If you don't regard arrays as members
of the class of string types, then you can reduce Ada's count
accordingly.

In addition, one of the major arguments the Ada fans have used here is
that Ada's strings are built-in, NOT added as a class like in C++. If
C++ had been designed from the beginning with a string class, the
array-based "stuff" probably wouldn't exist at all.

I don't see what difference it makes whether the type is built-in or
not. What's wrong with an added class? Perhaps they were refering to
the fact that you can declare array objects (strings) with non-static
bounds on the stack (since clearly Unbounded_String is not a built-in
type).

BTW, in case anybody really cares, yes I apply the same standard to
C++: while its string handling facilities are fewer and IMO better than
Ada's, they're still far short of perfect.

I prefer string handling in C++ too, but not being able to declare an
array (on the stack) with non-static bounds is a real pain sometimes
(although std::string mostly compensates for this). I agree that Ada's
string handling facilities aren't as nice, but they do get the job
done.
 
I

Ioannis Vranos

Georg said:
How well does this style of passing information work across thread
boundaries?


Do you mean throwing an exception in one thread and catch it in another?

(Not debating the usefulness of the mechanism. Although
I think it deserves to be separated from exception handling.)



Actually it is bot separated, in C++ all standard library exception
classes are (ordinary classes) derived from the base class exception
defined in <exception>.
 
R

Robert A Duff

Jerry Coffin said:
In addition, one of the major arguments the Ada fans have used here is
that Ada's strings are built-in, NOT added as a class like in C++.

*Some* Ada fans have used that argument, but I'm an Ada fan, and I don't
agree with it. I happen to think that (other things being equal) it's
better to put functionality into libraries than to build them into the
syntax and semantics of the language.

- Bob
 
R

Robert A Duff

Martin Dowie said:
Almost certainly backwards compatibility - but I'm sure Bob and/or Randy
could shed more light on that...

Well, actually, during the Ada 9X design I tried to push for a
class-hierarchy of exceptions. I don't like every detail of the way C++
does it, but at least in *this* regard, it's better than Ada.

Jerry Coffin is wrong that Ada does not allow attaching information to
exception, by the way. Ada allows attaching Strings, which is
admittedly a kludge. Using the class-hierarchy, as Jerry advocates,
would be cleaner, and type safe.

- Bob
 
R

Robert A Duff

Jerry Coffin said:
...effort that's put into
compile-time checks more or less directly translates into time and
effort that was NOT put into better code generation and optimization.

True, but I think you misunderstood Peter Amey's point. I believe he's
not talking about run-time checks that can be optimized away with some
compiler effort, but about purely compile time rules. For example, both
languages have visibility rules, but I find Ada's visibility rules to be
less error prone than those of C++.
Maybe...or maybe not. IME, absolute statements about generalities (e.g.
all implementations of a language) are rarely accurate. Ada compilers
vary quite widely, and I've certainly seen some emit code that included
checks that were logically unnecessary. I'd guess that the current
compilers are better, but perfection in this respect would surprise me.

It would surprise me, too, since it's provably impossible!
This is what Appel calls the full employment act for compiler
writers: no matter how smart a compiler is at optimizing,
you can always make it smarter. And that's formally provable.

The real question is to what extent can checks be optimized away,
and how often one needs to resort to suppressing them, and this question
can only be answered via measurement. By "measurement" I don't mean
bogus benchmarks written to make a point on one side or the other. ;-)

By the way, *most* of the work a compiler does to optimize away checks
is the same as for other optimizations (despite what some Ada fans have
claimed in this thread), so optimizing away checks is not as costly as
you seem to think (in terms of compiler-writer's effort).
Some areas are somewhat more questionable -- calling a class a "tagged
record" is clearly a mistake, ...

Sorry, but if you think a class is called a tagged record in Ada,
you don't understand the language.
... but it's open to question whether it
should be classified under poor expression of the concept, or just
general idiocy.

;-)

- Bob
 
G

Georg Bauhaus

Ioannis Vranos wrote:

I can't understand why your code has faster access (I assume you mean
run-time efficiency).

Door_Count array access is faster because while it acts like
std::map<Floor_Number, unsigned int>, it is really an array.

Omitting the association of the indexing number numbers (-2 .. 52) with
the floors for the moment, these tests should demonstrate:

#include <map>
#include <hash_map> // GNU: #include <ext/hash_map>, __gnu_cxx::hash_map
#include <valarray>
#include <vector>

#define M 55 // array size
#define N 10000 // assigments
#define R 5000 // runs


struct Test { // compare random access to keyed access

void arrays() {
int a[M];

for (int k = 0; k < N; ++k)
a[k % M] = k;
}

void valarrays() {
std::valarray<int> a(M);

for (int k = 0; k < N; ++k)
a[k % M] = k;
}

void vectors() {
std::vector<int> a(M);

for (int k = 0; k < N; ++k)
a[k % M] = k;
}

void maps() {
std::map<int, int> a;

for (int k = 0; k < N; ++k)
a[k % M] = k;
}

void hash_maps() {
std::hash_map<int, int> a;

for (int k = 0; k < N; ++k)
a[k % M] = k;
}

};

int main()
{
Test t;

for (int run = 0; run < R; ++run)
t.arrays();
// t.valarrays();
// t.vectors();
// t.maps();
// t.hash_maps();

return 0;
}
To give another example, .NET does not provide such an array container
either, in its own containers collection. So why such a mainstream
framework does not provide an array type with negative indexing either?

C# does provide fixing arrays.

I think we can't buy high speed computing components from the
producers of .NET. However, Fortran for .NET is available. (Doesn't mean
the producers of libraries will use non-default index value in Fortran code.)
So is APL.

This is not some kind of general proof, but for me it is an indication.
Again, I agree that boundary checking etc are useful and should be added
in C++ perhaps with additional keywords.

Have you had a look at D?

Just to be technically accurate. C++ has fixed size built in arrays. It
doesn't provide range checking for them though.

OK. And lets see what happens when the C99 arrays will be adopted.

Georg
 
J

Jerry Coffin

Larry said:
Really ?

Even programs I write for my own personal use are run _many_ more
times than they are compiled. Personally, I often spend compile
time thinking some more about the problem, sometimes to good
advantage :)

Being compiled isn't the major cost either.

For an awful lot of software, being run multitudes of times doesn't
make speed important -- interactive software (for one example) has
something on the order of really soft real-time requirements. I.e. too
slow is mildly annoying, but any response time under 100 ms or so
qualifies as "instant", and after that making it 100 or even a million
times faster rarely accomplishes much.
It does not provide a preprocessor, for safety reasons.

Look again at the wording -- I spoke in terms of the capabilities that
C happens to provide as what's generally called the preprocessor. I
could say "phases 1 through 6 of translation" if I wanted to be more
formal, but it's utterly irrelevant.

Regardless of the wording, however, I think this is (mostly) a
red-herring. What do you consider unsafe about (for example) some chunk
of code being compiled only when I want it to be? If I really believe
in the compiler's optimizer, I can already do things like "if False" in
Ada, and that code clearly won't ever execute. It just happens that C
and C++ provide a simple and practical method of doing the same things
in a way that's easy to externally control.
But what programming step (as distinguished from construction trick)
can only be performed from a preprocessor ?

Attempting to separate programming from constructing (a program) seems
to me a strong indication that you don't really know much of what
you're talking about. Regardless of this, however, the fact is that
even in Ada people who have a preprocessor available (e.g. with GNAT)
frequently find it extremely useful -- but using it renders the code
completely non-portable.
I see no mistake.

There is none so blind as he who will not see. The biggest problem is
that "tagged record" is a low-level description -- i.e. it's about the
implementation, not the real concept. A secondary problem is that in
other Pascal-family languages (e.g. Pascal, Modula II, Modula 3 and
probably Oberon), a "tag" is the distinguishing characteristics of a
variant record, having nothing to do with object orientation.
Is it possible your background in Pascal is inadequate
and overwhelmed by your background in C* languages.

Pascal has records, but not "tagged records". I don't believe Modula
II, Modula 3 or Oberon uses such poor terminology either. I don't see
how background in C signifies at all, since it doesn't use "record",
"tagged record" or "class" at all. I suppose one could point out that C
uses names that reasonably accurately reflect what's being discussed,
but I have a hard time calling that a bad thing...

OTOH, if you look through a language-neutral book on object oriented
programming, you'll "class" used to name a rather general concept quite
routinely. By contrast, I've yet to see "tagged record" used to
describe anything except the syntax of Ada 95.
 
G

Guest

kevin cline said:
But not all lines of source code are created equally. Written in a
more expressive language the application might be only half that size,
or most likely even less.
Ada is every bit as expressive as C++. There is not likely to be
any improvement in the number of KSLOC using C++. Oh, yes,
if we choose to use a cryptic form of C++, with all the little
shortcuts that make the code less readable, we might achieve
some reduction in the KSLOC, but at what cost in understandability?

Richard Riehle
 
G

Guest

Ioannis Vranos said:
Believe it or not, I do not understand most of Ada code, apart from some
Pascal-like constructs here and there. :)
I am not asking, which non-C++ programmer will understand the code. I am
suggesting that the code will be less-than obvious to many C++ programmers.
Certainly, after careful study, the experienced C++ programmer might be
able to read your example, but there is room for misinterpretation unless
one is supplied a fair amount of documentation.

Also, if you are unfamiliar with Ada to the point where you cannot read
the code, I find it strange that you are so willing to publicly criticize it.

I am required to understand C++ code because of my daily working
conditions. My criticisms of it are mostly due to my direct experience
with it. Your criticisms of Ada seem to derive from your lack of
experience. Perhaps a little more study and preparation would be
helpful. In fact, once you understand contemporary Ada, you might
be a bit less quick to criticize it.

Richard Riehle
 
I

Ioannis Vranos

I am not asking, which non-C++ programmer will understand the code. I am
suggesting that the code will be less-than obvious to many C++ programmers.
Certainly, after careful study, the experienced C++ programmer might be
able to read your example, but there is room for misinterpretation unless
one is supplied a fair amount of documentation.


Any intermediate C++ programmer should be able to understand my examples.

Also, if you are unfamiliar with Ada to the point where you cannot read
the code, I find it strange that you are so willing to publicly criticize it.


Who said I am criticizing it? As I have mentioned many times already I
like Ada (for me it is something like Pascal as it should have been in
the first place), and will probably learn it some time in the future.

However I am trying to set some things straight regarding unfair C++
criticisms (and when they prove fair, it's OK with me), and argue a bit,
on how this and that can be done in Ada and which is better.

My conclusion is that both languages share some common ideals and both
languages offer things that the other does not offer. Now which one
offers the most of them, is an entirely other subject.

In summary wecan say that both languages are mature and *both* do their
job. So it will be *unfair* to say that one of them is insufficient to
do application development or systems programming.

I am required to understand C++ code because of my daily working
conditions. My criticisms of it are mostly due to my direct experience
with it. Your criticisms of Ada seem to derive from your lack of
experience.


Personally I do not like Pascal. However I like Ada! And yes, I do not
know Ada. Also I do not think I am doing criticism, I am just checking
some features and arguing with Ada programmers which language provides
them better.


In this thread of course, there may be others who do not like Ada or C++
in any way. :)
 
D

Dr. Adrian Wrigley

If you provide some explanations, I will give you the C++ equivalent.

UpdateString takes an array indexed by integers, updating bottom
and top halves recursively in some obscure way.

The point is that the input parameter is an array with upper and lower
bounds which are arbitrary, and are different at each level of
recursion. I have created the arguments to the recursive call
by slicing the input parameter into two half arrays, with the
help of the array attributes ('First, 'Last, 'Length). Normally,
this takes place without any copying. No heap allocation is
required, and any accesses outside the intended array range for
updating at each level of recursion are excepted.

The most obvious C++ implementation is with vectors, but I think
you need three additional parameters and several checks to get
equivalent semantics. The three new parameters might be
'StartElement' 'EndElement' and 'BaseOffset'. You need the
BaseOffset to accommodate the vectors always starting at 0,
so you can find the problem-domain start.

You may get into problems if the procedure needs to call
other functions that take a vector, if they are unable to
take upper and lower limits to process. Can you make a
vector which is a slice of another vector without copying
all the elements in and out?

This kind of recursive slicing of arrays is something I
have found *much* more natural and reliable in Ada than in C,
where hacking with pointer arithmetic and extra parameters
would be the usual solution.

Hope this helps.
 
I

Ioannis Vranos

Georg said:
Door_Count array access is faster because while it acts like
std::map<Floor_Number, unsigned int>, it is really an array.

Omitting the association of the indexing number numbers (-2 .. 52) with
the floors for the moment, these tests should demonstrate:

#include <map>
#include <hash_map> // GNU: #include <ext/hash_map>, __gnu_cxx::hash_map
#include <valarray>
#include <vector>

#define M 55 // array size
#define N 10000 // assigments
#define R 5000 // runs


struct Test { // compare random access to keyed access

void arrays() {
int a[M];
for (int k = 0; k < N; ++k)
a[k % M] = k;
}

void valarrays() {
std::valarray<int> a(M);
for (int k = 0; k < N; ++k)
a[k % M] = k;
}

void vectors() {
std::vector<int> a(M);
for (int k = 0; k < N; ++k)
a[k % M] = k;
}

void maps() {
std::map<int, int> a;
for (int k = 0; k < N; ++k)
a[k % M] = k;
}

void hash_maps() {
std::hash_map<int, int> a;
for (int k = 0; k < N; ++k)
a[k % M] = k;
}

};

int main()
{
Test t;

for (int run = 0; run < R; ++run)
t.arrays();
// t.valarrays();
// t.vectors();
// t.maps();
// t.hash_maps();

return 0;
}



I am not sure what you mean with the above, perhaps to use the
facilities of <ctime> to measure their performance? Of course vector is
faster than map.


C# does provide fixing arrays.


You mean it can use signed indices? Look, just to be technically
accurate, C++ can also use negative indices, but I avoided mentioning it
because I considered it an unnecessary feature (again why then someone
did not provide an array container with signed indices as the default,
since it can be done?). But here is an example:


#include <iostream>
#include <vector>

int main()
{
using namespace std;

vector<int> vec(10);

vector<int>::iterator pi= vec.begin()+4;

// Makes vec[2]== 4.
pi[-2]= 4;

pi[1]= 3;

pi[0]= 9;


//built in array
int somearray[4];

int *p= somearray+2;

//Makes somearray[1]== 9
p[-1]= 9;
}


I think we can't buy high speed computing components from the
producers of .NET. However, Fortran for .NET is available. (Doesn't mean
the producers of libraries will use non-default index value in Fortran
code.)
So is APL.


In any case, with C++/CLI, C++ becomes the systems programming language
of .NET.

OK. And lets see what happens when the C99 arrays will be adopted.

Do you mean C99's built in Variable Length Arrays (VLAs)? I do not think
they will be adopted in C++.
 

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,057
Members
47,665
Latest member
salkete

Latest Threads

Top