From: Andrei Alexandrescu (See Website For Email) on
Andrei Alexandrescu (See Website For Email) wrote:
> James Kanze wrote:
>> On the other hand, it's impossible to eliminate it entirely;
>> some of it comes directly from the hardware we run on, and
>> eliminating other cases (e.g. some of the threading issues)
>> really does impose unacceptably high run-time costs.
>
>
> IMHO the whole non-deterministic hardware branch of discussion is a big
> smelly red herring pulled on the trail. This is not a hardware forum. We
> discuss the whole issue within the confines of a hardware model, and
> artificially taking the discussion to metaphysical levels would only
> lead to purpose-of-life kind of questions.

I misquoted the text I was answering to. My text above was in response
to the reference to the hardware behaving erratically when dropping the
voltage supply by 20%. Sorry for the confusion.

Andrei

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Al on
Hi there,

Gabriel Dos Reis wrote:
> Sorry, I was looking for logical, intrinsic, reasons. If he had, I've
> missed it. Upon reading you reply, I searched again; I'm afraid I
> must have missed it again.

Below, hopefully :).

> | (Dynamic) Strings and (Dynamic) Arrays are just as
> | common and important in the vast majority of programs as Integers.
>
> Dynamic strings and dynamic arrays are important; I'm not sure they are
> just as important as integers. But considering, for the sake of the
> argument, that they are equality important, it does not necessarily
> follow that they must be intrinsic in the language, if the language
> provides general effective abstraction tools to define strings and
> arrays in library efficiently.
>
> | Integers are an intrinsic part of the language, yet they don't need to.
> |
> | I see no indication that a language couldn't get away with a single type
> | -- bit -- and everything else left to the library. Thus, the same
> | argument applies to strings and arrays.
>
> I'm sure you can exhibit a logical, intrinsic, reason without
> resorting to proof by analogy -- which is considered by many as fraud.

This is not exactly a proof by analogy. Here are two simple reasonings:

In comparison to integers (short version):

1. You agree (at least for the sake the argument) that strings and
dynamic arrays are as important as integers.
2. Integers are important enough to be intrinsic to the language.
3. Thus, strings and dynamic arrays should also be intrinsic to the
language.

Or, stand-alone (longer):

1. Anything sufficiently common and important deserves syntactic and
semantic privilege.
2. Libraries can not and do not offer said privilege.
3. You agree (at least for the sake the argument) that strings and
dynamic arrays are sufficiently common and important.
4. Therefore, strings and dynamic arrays should not be relegated to a
library.
5. Thus, strings and dynamic arrays should be intrinsic to the language.


> | To be fair, std::string and std::vector are fairly impressive bits of
> | work, considering how they are constrained. But their deficiencies show
> | up everywhere.
>
> Are their deficiencies intrinsically linguistic that cannot be
> repaired, or are they library design artefacts?

There are certainly library design artifacts (Like the fact that a
vector doesn't easily offer a pointer to its data unlike a string). Or,
for instance, the fact that the string class offers very little
functionality (Split & Trim come to mind as missing).

But other deficiencies are intrinsically linguistic. Starting with the
fact that a "string" literal is really a pointer to memory that Must Not
Be Touched, yet it unceremoniously decays to non-const. This seems
fairly unsafe to me.

Another issue is that some concatenation is impossible:

const char* b = "b";
const char* x = "a" + "b"; // error
const char* y = "a" + 'b'; // corrupt
const char* z = "a" + b; // error

Yield weird results. Operator overloading helps, but the warts do show.

Another issue is the very unfriendliness of const char* peppered
throughout the language and the libraries where `string' would be much
more semantic. And it isn't even just the C libraries that use it. C++
items like what() in exception or name() in type_info use it too.

Finally, there's arrays. As Walter pointed out, arrays in C++ were
basically abandoned in favor of vector or <your favorite container> when
it would be much more useful for the language to provide that
functionality. In the vast majority of cases one doesn't need specific
container functionality and guarantees, rather simply a quick way to
build and manipulate an array /safely/.

Here's with vector:

#include <vector>
//...
std::vector<int> array;
array.push_back(1);
array.push_back(2);
array.push_back(3);
array.push_back(42);
array.push_back(666);
cout << array.size() << endl; // 5


And here's how it should be:

int[] array = [1, 2, 3, 42, 666];
cout << array.size << endl; // 5


People simply /expect/ an array to automatically know its size. A naked
pointer is plain unreasonable. I've seen this very question asked a
million times, with the same answer: No, the array does not know its own
size. What's most ironic is that it would seem to me that arrays
actually /must/ know their size internally in order for delete[] to work.




> | Can you imagine having to do:
> |
> | #include <integer>
> |
> | // Binary for 32, because remember, you don't have int literals.
> | typedef std::integer<0, 0, 1, 0, 0, 0, 0, 0> int32;
>
> I don't know what you mean by that.
> I tried it on my compiler, it choked with:

Sorry, I was just being facetious. Clearly there's no <integer> header,
it was a fictitious example to prove my point.

> Again, please explain the logical idea you wanted to express.

The idea is that life would be horrible without built-in integers and
integer literals, when as I mentioned before, they _don't need_ to be in
the language. They could be relegated to a library, but aren't because
the need for them is so great and so common. The need for dynamic arrays
and strings is _at least_ as great and common in my experience, to
warrant intrinsic support for them.


Thanks,
-Al.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Mirek Fidler on

Walter Bright wrote:
> Nevin :-] Liber wrote:
> > So what is it about C++ that is stopping you from applying the
> > optimization you use for the intrinsic complex to std::complex (and
> > then, in general, to objects that have a similar form to std::complex)?
>
> Having constructors causes problems for it. Even though indirection can
> often be removed by the optimizer, the decisions about how returns are
> done are made in the parsing stage, because it affects how constructors
> are set up to get the return type built on the caller's stack. The
> optimizer/code generator really only see the C-like result of all that.

Just to keep things clear, we are here speaking about non-inlined
functions, are we?

Mirek


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Gabriel Dos Reis on
Walter Bright <walter(a)digitalmars-nospamm.com> writes:

| Gabriel Dos Reis wrote:
| > Walter Bright <walter(a)digitalmars-nospamm.com> writes:
| >
| > | Gabriel Dos Reis wrote:
| > | > Fortunately, not all compilers out there made the decision to actively
| > | > unsupport abstractions like the Digital Mars compiler.
| > |
| > | Name one that returns std::complex values in a register pair.
| >
| > I did in the part that was consciously left out from your reply.
| >
| > GCC/g++.
|
| You didn't mention GCC/g++ or x86-64. You mentioned the PowerPC and the
| Itanium. It's hard to elide something that wasn't there.

I did mention the "common C++ ABI" specification and did give a publically
accessible link. The very first section (Acknowledgements) of that
document says:

This document was developed jointly by an informal industry
coalition consisting of (in alphabetical order) CodeSourcery,
Compaq, EDG, HP, IBM, Intel, Red Hat, and SGI. Additional
contributions were provided by a variety of individuals.


I must confess that I thought an implementor intending to produce a
C++ implementation suitable for production use or discussing
fundamental C++ issues regarding efficiency would have a knowledge of
that ABI or at least heard of it, and would have followed the link if
he/she did not already know it existed. I know realize that there may
be various reasons why a C++ implementor may not know about it, or
would decide to ignore it outright. My mistake.

[...]

| Good for g++ on the X86_64.

I'm glad to see we know settle the issue of compilers returning UDT in
registers. I'm hoping that more C++ compiler implementors serious
about performance would actively support C++ abstractions, for example
through better ABIs, support for C++ idiomatic constructs, etc.

--
Gabriel Dos Reis
gdr(a)integrable-solutions.net

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: David Abrahams on
"Greg Herlihy" <greghe(a)pacbell.net> writes:

> David Abrahams wrote:
>> "Andrei Alexandrescu (See Website For Email)"
>> <SeeWebsiteForEmail(a)erdani.org> writes:
>>
>> > There might be a terminology confusion here, which I'd like to clear
>> > from the beginning:
>> >
>> > 1. A program "has undefined behavior" = effectively anything could
>> > happen as the result of executing that program. The metaphor with the
>> > demons flying out of one's nose comes to mind. Anything.
>> >
>> > 2. A program "produces an undefined value" = the program could produce
>> > an unexpected value, while all other values, and that program's
>> > integrity, are not violated.
>> >
>> > The two are fundamentally different because in the second case you can
>> > still count on objects being objects etc.; the memory safety of the
>> > program has not been violated. Therefore the program is much easier to
>> > debug.
>>
>> Seriously?
>>
>> IME you're at least likely to crash noisily close to the undefined
>> behavior. If you make everything defined the program necessarily
>> soldiers on until one of your own internal checks is able to notice
>> that something went wrong. Or am I missing something?
>
> The idea that "undefined behavior" equates to a program crash is a
> popular misconception among C+ programmers,

Yes, but not one that I share. I just said a crash was likely.

> And much of the time, the C++ programmer is right: the undefined
> behavior does terminate the program - but no credit should go to
> C++.

Not quite true. When a program enters "undefined behavior territory"
the implementation (or a 3rd party tool) is free to take the ideal
action. Undefined behavior is about implementor freedom, too.

> Rather it is the OS and the runtime that have filled in where the
> Standard has been remiss, by defining otherwise undefined behavior. An
> obvious example is the dereferencing of a NULL pointer - the
> consequences of which are undefined by the Standard, but defined on
> almost every modern architectures as a fatal memory access error.

Yes, but fortunately the response is observably outside the normal set
of results that the program can produce. Defined behavior is nicely
corralled off from everything else and (yes, in this case and not in
all cases) there's no chance of soldiering on without being able to
observe the problem.

> And in fact in none of these problematic examples cited in this
> discussion, lend any support to the believe that a C++ program would be
> any more likely to terminate than the Java program in the same
> situation. Certainly non-atomic accesses are likely to be too expensive
> to detect on a given hardware, and I'm not familiar with any such
> error. Of course the reverse argument could also be made: that C++'s
> undefined behavior be no different than that of the Java program, so
> C++ is none the worse of for it. But if undefined behavior were so
> well-behaved, then why can't the Standard just state that that is the
> case?

I don't understand what you're suggesting, but the answer is simple:
implementor freedom.

>> I don't have any real experience with Java, but Python generally
>> exhibits Java-like behavior, and I don't find it easier to debug
>> than C++.
>
> I have found Perl almost trivially easy to debug compared to a C++
> program. With C++programming there are two levels of correctness to
> worry about: first, the program must behave correctly (that is, have
> defined behavior at all times) and, second, this correct behavior must
> match the behavior that the programmer wants. A Perl (or Java)
> programmer does not have to worry about the first level, the program is
> always behaved - in other words, it always does what the programmer
> tells it to do.

To a first approximation, that's true in C++ until you tell the
program to do something illegal.

> So the only concern left is for the programmer to tell the program
> what it should be doing in order so that it can produce the expected
> (or "correct") results. So in essence a Perl programmer is already
> halfway done writing a program compared against the starting point
> of a C++ programmer, and this is before eiher programmer has written
> a single line of code (OK, that's an exagerration, but it is a valid
> point nonetheless).

I can certainly agree that you've dramatically overstated your case
here.

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]