From: Maciej Sobczak on
AJ wrote:

>> No language manages to completely do away with undefined
>> behavior. Although C++ could surely do better in this regard;
>> there's a lot of unnecessary undefined behavior.
>
> I have doubts about that first assertion. Surely there are academic
> languages out there that do. Moreover, I wasn't aware that fully-managed
> (e.g. no unsafe/PInvoke), CLS-compliant C# contained any UB. Does it? I
> also think pure ECMAScript is safe in that regard.

If the language is absolutely free of any UB then you basically cannot
implement its own library in it - with I/O being the crucial part.
Of course, it is possible to define a language without UB and give it a
library that is "reach enough", but such languages are not what we would
call "system-programming languages" (try to find one).

And there is nothing like "reach enough library" anyway.

If the language is supposed to be used in things like implementation of
whole operating systems, then some "reasonable" dose of UB is in order.
Of course, it's good if it's as controlled and confined as possible, but
you cannot eliminate it entirely - that's where "reasonable" comes in.


--
Maciej Sobczak : http://www.msobczak.com/
Programming : http://www.msobczak.com/prog/

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

From: James Kanze on
AJ wrote:
> Hi there,
> James Kanze wrote:
> <snip>
> > That depends. Library support isn't as good as core support
> > when it isn't as good. The fact that it is library and not core
> > isn't a disadvantage per se---I'd say that almost the opposite
> > is true. But you do have to compare the level of support; there
> > are some things that simply cannot be supported in a library
> > alone.

> I think I agree, though I also think we need a clear definition of a
> "library" and of "core-language" support. It is unclear at this point
> whether a library can be "magic" in the sense that it does things a
> regular user couldn't.

Of course it can be. There's no I/O whatsoever in the core C++,
so you couldn't write to a file unless there's some extra magic.
In some cases, the actual reason for putting something into the
library is that it cannot be implemented without magic.

> It is also unclear what is meant by C++ any more. Is C++ simply the
> language, or does it include the STL? I don't think I would include the
> STL into the definition of the "core" C++ language.

Formally, C++ is defined by ISO 14882: if something is in ISO
14882, it's part of C++, if it's not, it's not. In practice, of
course, we tend to use a looser definition, and most people
would consider things like Boost as "C++" in some sense of the
word, not strictly speaking part of the language, but certainly
something available and to be used.

> >> Here's one example: Multi-threading and thread safety.

> > And this is one of them: you definitly have to specify at the
> > language level when it is safe to access objects, and when not.

> >> For 1: In D, this is achieved in a super-clean and succinct manner:
> >> Adding a synchronized keyword.

> > That, on the other hand, is a serious defect, at least if it is
> > done as in Java. It forces locking to obey scope rules.

> How is this a serious defect? It merely follows RAII, which is among
> C++'s strengths (say, vs. C#/Java). This seems very orthogonal to me.

One of C++'s strengths is that you CAN define classes which
release resources in their destructor. Another is that they are
exactly that: classes, and that you can use them in many
different contexts, e.g.: shared_ptr< mutex::scoped_ptr >. Or
access the same facilities without using them at all---I see no
reason why you couldn't e.g. unlock a mutex in the "destruction
function" of a shared_ptr to something else.

Note too that even with an on stack object, you can "prepare" in
scope before e.g. acquiring the mutex.

Just because an idiom is superior 95% of the time doesn't mean
that we have a right to ban the other 5% of the uses.

> >> In C++, one must add error-prone boilerplate for critical
> >> sections (or mutexes, or locks) and in general the syntax is
> >> verbose and a hassle.

> > I've never noticed this. My experience in Java is that the
> > synchronized keyword is a major problem; it's much easier to
> > write effective, correct code in C++ (using e.g. boost::mutex).

> I'm not very familiar with Java's synchronized, unfortunately. I'll try
> to read up on it.

The problem is that 1) it forces synchronization to obey scope,
absolutely and always, and 2) it is bound to an object---you end
up doing "new Object" just to get a mutex.

> >> For 2: In D, synchronized is built-in. No need to download or
> >> install anything else. No need to check additional
> >> documentation on library usage.

> > I'm not sure I understand this point: if the functionality is
> > part of the standard library, there's also no need to download
> > or install anything else, and what's the difference between
> > having to check library documentation, and having to check
> > language documentation? The standard library IS part of the
> > language.

> Well, this is a tricky semantically (what is what), as I mentioned
> above. The point is that, as it stands, I believe there is _no_ C++
> support for synchronized of any sort, without relying on an external
> library.

At present, there is NO C++ support for synchronization of any
sort, period, since it is impossible to provide the support in a
library. So we end up counting on extensions to the Posix
support, or whatever, which is really only specified for C.

This is a recognized problem, the committee is working on it,
and my impression is that the committee feels that it is one of
the most important problems---whatever else may happen, the next
version of C++ will not ship without some sort of thread
support.

[...]
> >> One other serious legacy flaw in D (inherited from C/C++) is that it
> >> doesn't do away with undefined behavior. It's close, I think, but it's
> >> unfortunate that the holes aren't closed entirely.

> > No language manages to completely do away with undefined
> > behavior. Although C++ could surely do better in this regard;
> > there's a lot of unnecessary undefined behavior.

> I have doubts about that first assertion. Surely there are academic
> languages out there that do.

Not and provide thread support. (There probably are academic
languages which avoid it completely. At a cost of not providing
enough other features to be useful for anything.)

> Moreover, I wasn't aware that fully-managed
> (e.g. no unsafe/PInvoke), CLS-compliant C# contained any UB. Does it?

I don't know about C#, but Java has some. Precisely in the case
where two threads access the same object without the necessary
locks. I'd be very surprised that C# managed to avoid that one
as well---doing so has an enormous cost in run-time. (Of
course, they don't call it undefined behavior. That would be
uncool. But the actual effect is exactly the same.)

> I
> also think pure ECMAScript is safe in that regard.

I'm not familiar with it, but you may be right. I suspect that
a purely scripted language could be made to avoid all undefined
behavior. If nothing else, just put a lock around every
instruction.

> >>> However, what is important is whether a programmer can do his/her task
> >>> efficiently with the language and the associated tools, not whether it
> >>> is done by the core language or by the standard library or by a
> >>> third-party library. Whether a language facilitates good libraries or it
> >>> hinders good development tools, much of the credit/blame is to the language.

> >> 'Efficiently' is the key. Addi
From: James Kanze on
Frederick Gotham wrote:
> Andrei Alexandrescu (See Website For Email):

> > Ouch. Unless this is a joke, I can only be happy that your opinion isn't
> > shared by many :o). Why would you think undefined (I think you really
> > meant "unspecified") behavior is a good thing?

>
> Well, if we make it undefined behaviour to cast a random integer value to a
> "pointer to a double", to store the max value in it, and to increment it,
> then the implementation doesn't have to worry about what to do in case of:

> ++( *(double*)RandomInt() = numeric_limits<double>::max() );

I think that there are two types of undefined behavior. I have
no problem with the undefined behavior that results from a
reinterpret_cast, and it is necessary in order to support things
like memory mapped I/O. On the other hand, I find it most
disconcerting that an expression like *p = (*q) ++ is undefined
behavior if p and q happen to point to the same object. And
while strictly speaking not undefined behavior, it find it most
unacceptable that something like "f( std::auto_ptr( new X ),
std::auto_ptr( new Y ) )" is not exception safe.

These sort of things trap up beginners. And non-beginners as
well. Most of us have enough other problems to keep us busy
without having to constantly worry about such nagging
inconsistencies.

--
James Kanze (GABI Software) email:james.kanze(a)gmail.com
Conseils en informatique orient?e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34


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

From: James Kanze on
Walter Bright wrote:
[...]
> The easiest way to deal with roundoff errors is to increase the
> precision.

It's also the most naive:-). If you're loosing one bit
precision per iteration, and you're iterating a couple of
million times, you're going to have to increase the precision a
lot.

And please take this in the somewhat humorous veine it is meant.
Increasing precision is a solution sometimes, and I'm pretty
sure that you do understand the problems, and know enough to
verify that it is the correct solution in your case. But just
as obviously, it's not a silver bullet, and it won't really help
the naive user.

> Any compiler that doesn't at least provide the full precision
> of the underlying hardware cannot be taken seriously as a tool for doing
> serious numerical analysis. It tells me the compiler vendor has some
> agenda other than paying attention to the numerics crowd, and I wouldn't
> use such a tool for serious numerical work.

I think the problem is somewhat more complex. If you use long
double on an Intel, you do not have the guard bits and other
stuff that helps ensure correct rounding. As I understand it,
the idea behind extended precision was that it should be used
for intermediate results, and not for storing data---the idea is
that an expression like a*b/c will always give the "correct"
results if the correct results fit in a double.

Of course, this leads to confusion as well, since we don't
always know when the compiler will spill to memory, and when it
will keep the value in a register (with extended precision).

[...]
> Unlike C++, a conforming D compiler is *required* to provide a type
> representing the max precision the underlying hardware is capable of.

For what definition of "the underlying hardware is capable of"?
With proper software support, the underlying hardware is capable
of just about any precision I care to ask of it. Obviously,
this isn't what you mean, but while I think what you mean may be
obvious on most general purpose machines, I'm not sure that it
is precise enough for a standard.

The C++ standard, of course, follows the lead of C, and allows
the compiler to use extended precision in intermediate results,
without requiring it. The results can be surprising, to put it
mildly.

> And btw, g++ does offer 80 bit long doubles on the x86. Kudos
> to the gcc implementors.

I'm willing to bet that even VC++ uses extended precision on an
x86, even if it won't allow you to declare a variable of that
type. Not doing so slows down the math processor considerably.

--
James Kanze (GABI Software) email:james.kanze(a)gmail.com
Conseils en informatique orient?e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34


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

From: David Abrahams on
Walter Bright <walter(a)digitalmars-nospamm.com> writes:

> any library can be implemented in any language.

To buy into that idea, you have to believe that the expressiveness of
a library's API and its performance characteristics are not part of
the library design itself.

You can write Blitz++ in FORTRAN? I don't think so. If you do that,
it ceases to be Blitz++, and becomes something else.

--
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! ]