Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Shortened names

9 views
Skip to first unread message

Frederick Gotham

unread,
Jul 11, 2006, 8:38:15 AM7/11/06
to

This is mostly about my own personal taste, but still I'd like to express
my opinion:

I'd like to suggest to the Committee that they use identifiers as short as
possible for future additions to the standard. I like names such as:

pow
memcpy
fmod
qsort
strlen
puts
malloc

In the current Standard, I particularly think the new-style casts are
monstrosities:

static_cast
dynamic_cast
reinterpret_cast

They take up a disproportionate amount of horizontal screenspace, and are a
lot less pleasant to have to type out (particularly "reinterpret_cast").

I would prefer the likes of:

alignof

instead of:

alignment_of


Of course, this is just my own opinion, and others' opinions may differ...
but nonetheless I'd like to throw in my two cents.

--

Frederick Gotham

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std...@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]

kuy...@wizard.net

unread,
Jul 11, 2006, 12:04:49 PM7/11/06
to
Frederick Gotham wrote:
> This is mostly about my own personal taste, but still I'd like to express
> my opinion:
>
> I'd like to suggest to the Committee that they use identifiers as short as
> possible for future additions to the standard. I like names such as:
>
> pow
> memcpy
> fmod
> qsort
> strlen
> puts
> malloc
>
> In the current Standard, I particularly think the new-style casts are
> monstrosities:
>
> static_cast
> dynamic_cast
> reinterpret_cast
>
> They take up a disproportionate amount of horizontal screenspace, and are a
> lot less pleasant to have to type out (particularly "reinterpret_cast").
>
> I would prefer the likes of:
>
> alignof
>
> instead of:
>
> alignment_of
>
>
> Of course, this is just my own opinion, and others' opinions may differ...
> but nonetheless I'd like to throw in my two cents.\

The fundamental problem with short identifiers is that they are
popular, for precisely the reasons you give. As a result, the shorter
and more reasonabley a keyword is, the more likely it is to clash with
a name already in use by existing code. Namespaces reduce this problem,
but for unqualified names, they do not eliminate it.

The *_cast operators are a special case, however. Most conversions that
don't occur implicitly are dangerous, at least in some contexts.
Therefore, the explicit cast operators were deliberately made long and
unwieldy, to discourage the unnecessary and inappropriate use of casts,
and to make it easier to locate them when they are used.

Victor Bazarov

unread,
Jul 11, 2006, 11:24:08 AM7/11/06
to
Frederick Gotham wrote:
> [...]

> I would prefer the likes of:
>
> alignof
>
> instead of:
>
> alignment_of
>
>
> Of course, this is just my own opinion, and others' opinions may
> differ... but nonetheless I'd like to throw in my two cents.

Here my half-penny: 'alignof' is not English. 'alignto' is, e.g.
If you want abbreviations, they need to follow some kind of convention
like 'alimntof' (so it's clearer that it's a noun, not a verb like
"align" or "copy" or "put").

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

Krzysztof Żelechowski

unread,
Jul 11, 2006, 11:25:26 AM7/11/06
to

Użytkownik "Frederick Gotham" <fgot...@SPAM.com> napisał w wiadomości
news:D3Msg.11332$j7.3...@news.indigo.ie...

>
> This is mostly about my own personal taste, but still I'd like to express
> my opinion:
>
> I'd like to suggest to the Committee that they use identifiers as short as
> possible for future additions to the standard. I like names such as:
>
> pow
> memcpy
> fmod
> qsort
> strlen
> puts
> malloc
>

These indentifiers are short because the classic C standard requires all
global identifiers to be distinguishable using their initial 6 characters,
case insensitive. In order to comply with the standard and to make this
rule express and instantly visible, the standard C library implementors
chose to make this rule explicit by limiting the length of those identifiers
to 6 letters lowercase. It is not obeyed consistently, e.g. "memmove" is
equivalent to "memmov", but you have the idea.

> In the current Standard, I particularly think the new-style casts are
> monstrosities:
>
> static_cast
> dynamic_cast
> reinterpret_cast
>
> They take up a disproportionate amount of horizontal screenspace, and are
> a
> lot less pleasant to have to type out (particularly "reinterpret_cast").
>
> I would prefer the likes of:
>
> alignof
>
> instead of:
>
> alignment_of
>
>
> Of course, this is just my own opinion, and others' opinions may differ...
> but nonetheless I'd like to throw in my two cents.

The identifiers printf and memcpy are "monstrosities" for every C language
student. Without knowing 6 character rule sparing one character from
memcopy is inexplicable. It gives no advantage in typing and makes the name
unreadable. And why did not they choose the identifier "memmve" as well?
The abbreviations are inconsistent and hard to learn.

On the other hand, nothing prevents you from #defining scast, dcast, rcast,
alignof and using them in your code. However, be warned that coining
abbreviations for casts is deprecated because their names are chosen to
constitute a physical discouraging barrier against abusing unsafe language
constructs, *especially* "reinterpret_cast", and to make the design of
static code analysis tools easier.

Burdening the committee with the duty of managing abbreviations and
shortcuts is unreasonable. And what happens if some C/UNIX addict prefers
algnof to alignof?

>
> --
>
> Frederick Gotham
>

Christopher Yeleighton

kanze

unread,
Jul 11, 2006, 12:32:28 PM7/11/06
to
Frederick Gotham wrote:
> This is mostly about my own personal taste, but still I'd like
> to express my opinion:

> I'd like to suggest to the Committee that they use identifiers
> as short as possible for future additions to the standard.

For what definition of "possible"? For example, the committee
could have used v, instead of vector, i instead of iterator, c
instead of complex... It would certainly be easier to type:

m< s, s >

than std::map< std::string, std::string >. (Obviously, if we're
making names as short as possible, we'll have to get rid of all
this std:: junk.)

There are 32949 legal two character names. I don't think off
hand that the library defines more symbols than that, so
strictly speaking, as short as possible means no identifier with
more than two characters. Of course, some of the names will
have to be pretty arbitrary---there are considerably less
countries, and look at some of the two letter abbreviations for
those (zh for China, for example).

> I like names such as:

> pow
> memcpy
> fmod
> qsort
> strlen
> puts
> malloc

The C++ replacements actually shorten most of those: sort,
instead of qsort, new instead of malloc, copy instead of memcpy,
size instead of strlen, << instead of puts. That leaves pow and
fmod--pow is probably optimal, given history and extra-C++
usage. But who knows, off hand, what fmod means? Especially
in the C library, which generally uses an initial f as an
indication that the function deals with FILE*. That one should
be clearer.

> In the current Standard, I particularly think the new-style
> casts are monstrosities:

> static_cast
> dynamic_cast
> reinterpret_cast

I think that's intentional. Tu discourage unnecessary use.

> They take up a disproportionate amount of horizontal
> screenspace, and are a lot less pleasant to have to type out
> (particularly "reinterpret_cast").

I can make the window on my screen 200 and some characters wide.
And I don't know if you realize this, but C++ allows line breaks
in expressions as well, so you can even use them and keep the
line length under 80 characters (as I do). And of course,
they're not something that occurs often in the code.

Note too that these are keywords. There are no namespaces to
prevent conflicts, and they were added relatively late. At
least a minimum effort was required to avoid having them colide
with likely identifiers in user code.

> I would prefer the likes of:

> alignof

> instead of:

> alignment_of

> Of course, this is just my own opinion, and others' opinions
> may differ... but nonetheless I'd like to throw in my two
> cents.

Readability is more important than writability---a program is
written once, but read many times. Readability is important.

Having said that, there are trade-offs involved. Something like
int is so frequent that anyone working in C or C++ will
recognize it immediately; very little, if any, readability would
be gained by replacing it with integer. On the other hand, C
experimented with replacing it with nothing---with the empty
string---in some contexts, and I don't think that that
experiment can be considered a success (although it's hard to
have an identifier with less than 0 characters in its name).
Similarly, I suspect that even you would object to using
arbitrary sequences just to get the name down to two characters.

In the end, the rule should be, first, consistency---you don't
call it getline (without an _) but find_end (with an _), and you
don't abbreviate something in one symbol, and not in another.
Beyond that, trying to find meaningful short names for
frequently used identifiers is probably a good idea: find is
probably a better name than
find_the_first_value_equal_to_the_third_argument, even if the
latter is arguably clearer. For something as little used as
alignment_of, however, who cares.

--
James Kanze GABI Software
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

Frederick Gotham

unread,
Jul 11, 2006, 2:10:01 PM7/11/06
to
posted:


> Therefore, the explicit cast operators were deliberately made long and
> unwieldy, to discourage the unnecessary and inappropriate use of casts,
> and to make it easier to locate them when they are used.


I really don't understand this reasoning.

A high-quality programming language like C++ should be designed for expert
programmers, not for people learning to program. There's plenty of
alternatives out there for the not-so-apt: Visual Basic, Java.

No expert programmer would use a cast unnecessarily, e.g.:

int i;

long j = (long)i; /* or static_cast if you prefer */


And who's to say if a cast is "inappropriate"... ?

C was built on a foundation of programmers who are competent, not on
holding the hands of beginners who aren't out of diapers yet. C++ should
build on this proud mentality.

My efficient, fully-portable, Standard-compliant code contains many casts.
Some are necessary to make the code compile. Some are necessary to suppress
compiler warnings. But they're all there for a reason!

Why should expert programmers be burdened with unwieldy names? It insults
human intelligence.

Some may hold in derision my use of old-style casts, but I'll definitely
prefer:

int *pi = (int*)pc;

over:

int *pi = reinterpret_cast<int*>(const_cast<char*>(pc));

--

Frederick Gotham

kuy...@wizard.net

unread,
Jul 11, 2006, 4:48:05 PM7/11/06
to
kanze wrote:
> Frederick Gotham wrote:
.

> have to be pretty arbitrary---there are considerably less
> countries, and look at some of the two letter abbreviations for
> those (zh for China, for example).

Actually, for native speakers of mandarin, zh makes a lot of sense,
since the mandarin word for China is Zhongguo.

.


> usage. But who knows, off hand, what fmod means? Especially

Floating point MODulus.

Keith Thompson

unread,
Jul 12, 2006, 12:15:16 PM7/12/06
to
fgot...@SPAM.com (Frederick Gotham) writes:
[snip]

> And who's to say if a cast is "inappropriate"... ?
>
> C was built on a foundation of programmers who are competent, not on
> holding the hands of beginners who aren't out of diapers yet. C++ should
> build on this proud mentality.
>
> My efficient, fully-portable, Standard-compliant code contains many casts.
> Some are necessary to make the code compile. Some are necessary to suppress
> compiler warnings. But they're all there for a reason!

Most of the casts I've seen that are "necessary to suppress compiler
warnings" are actually unnecessary; rather than fixing errors, they
mask them. I'm not necessarily suggesting that that's the case with
*your* casts, but I'd be interested in seeing examples where such
casts are necessary and useful.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.

James Dennett

unread,
Jul 12, 2006, 11:16:04 AM7/12/06
to
Frederick Gotham wrote:
> posted:
>
>
>> Therefore, the explicit cast operators were deliberately made long and
>> unwieldy, to discourage the unnecessary and inappropriate use of casts,
>> and to make it easier to locate them when they are used.
>
>
> I really don't understand this reasoning.

It helps to reduce defect densities.

> A high-quality programming language like C++ should be designed for expert
> programmers, not for people learning to program.

I think that C++ should recognize that its user base includes
people at various levels of expertise, from some of the experts
who inhabit forums such as csc++ through good professional
programmers, average professional programmers, weak professional
programmers, hobbyists, and people who use C++ as a tool
incidental to their primary line of work.

> There's plenty of
> alternatives out there for the not-so-apt: Visual Basic, Java.
>
> No expert programmer would use a cast unnecessarily, e.g.:
>
> int i;
>
> long j = (long)i; /* or static_cast if you prefer */

Innumerable bugs in code written by professionals have been
caused by casts that should not have been present.

> And who's to say if a cast is "inappropriate"... ?

A specification, a test suite, a coding standard, or a language
rule, for example.

> C was built on a foundation of programmers who are competent, not on
> holding the hands of beginners who aren't out of diapers yet. C++ should
> build on this proud mentality.

Many features of C would also be unnecessary if programmers
made no mistakes. const-correctness, for example. Or
function prototypes. C++ could abandon type-safe linkage
if we never made mistakes. Most type checking could be
discarded.

> My efficient, fully-portable, Standard-compliant code contains many casts.
> Some are necessary to make the code compile. Some are necessary to suppress
> compiler warnings. But they're all there for a reason!
>
> Why should expert programmers be burdened with unwieldy names? It insults
> human intelligence.

Most good programmers accept that they make mistakes, and
embrace tools and techniques that help to reduce the
frequency of those mistakes.

> Some may hold in derision my use of old-style casts, but I'll definitely
> prefer:
>
> int *pi = (int*)pc;
>
> over:
>
> int *pi = reinterpret_cast<int*>(const_cast<char*>(pc));

I'd want to see a comment for why constness is discarded. It
usually (though not always) indicates a defect, or at least a
week design.

I'm happy for C++ to continue to try to develop in a manner that
helps professionals and hobbyists to write code that is more
correct. Reducing the need for C-style casts is one small way
of moving in that direction; using less cryptic names for new
facilities is another.

-- James

kuy...@wizard.net

unread,
Jul 12, 2006, 12:17:41 PM7/12/06
to
Frederick Gotham wrote:
> posted:
>
>
> > Therefore, the explicit cast operators were deliberately made long and
> > unwieldy, to discourage the unnecessary and inappropriate use of casts,
> > and to make it easier to locate them when they are used.
>
>
> I really don't understand this reasoning.
>
> A high-quality programming language like C++ should be designed for expert
> programmers, not for people learning to program. There's plenty of
> alternatives out there for the not-so-apt: Visual Basic, Java.
>
> No expert programmer would use a cast unnecessarily, e.g.:

Most of the people who program in C++ are not experts. Most of the code
I've had to deal with in my job that wasn't written by me contains many
poorly written spots, and inappropriate use of casts is one of the most
popular kinds of defects. Also, it's not as if this is a major
inconvenience; the longer names can be partially justified simply by
the fact they're easier to search for. If you've ever had the
misfortune of having to track down all the places where a variable with
a name like 'i' is used, you start to appreciate the advantages of
longer identifiers.

> int i;

Perhaps you haven't had that misfortune yet.

>
> long j = (long)i; /* or static_cast if you prefer */
>
>
> And who's to say if a cast is "inappropriate"... ?

An expert can give you an answer to that which is many pages long.
Here's a few general categories of problems: A cast is inappropriate if
it produces the wrong result under circumstances the programmer failed
to consider. A cast is inappropriate if it causes an unnecessarily
wasteful extra step. A cast is inappropriate if it masks a defect due
the fact that the object being converted to the correct type should
have been declared with that type in the first place.

> C was built on a foundation of programmers who are competent, not on
> holding the hands of beginners who aren't out of diapers yet. C++ should
> build on this proud mentality.

C++ was deliberately designed to make it easier to avoid many of those
errors that your hypothetical "expert" programmers would never make,
but which real world programmers make all the time. For example, the
concept of constructors and destructors, and the rules that call for
them to be automatically invoked, make it a lot easier to avoid
problems associated with bookend code such as malloc()/free() and
fopen()/fclose().

> Why should expert programmers be burdened with unwieldy names? It insults
> human intelligence.

I think you're overrating human intelligence, if you take this as an
insult. Human intelligence is messy, inaccurate, and unreliable. Good
engineering practice, including the design of programming languages,
takes that into consideration.

> Some may hold in derision my use of old-style casts, but I'll definitely
> prefer:
>
> int *pi = (int*)pc;
>
> over:
>
> int *pi = reinterpret_cast<int*>(const_cast<char*>(pc));

Let me join the people who deride you for that choice.

kanze

unread,
Jul 12, 2006, 12:21:46 PM7/12/06
to
"Krzysztof Żelechowski" wrote:
> Użytkownik "Frederick Gotham" <fgot...@SPAM.com> napisał w wiadomości
> news:D3Msg.11332$j7.3...@news.indigo.ie...

> > This is mostly about my own personal taste, but still I'd
> > like to express my opinion:

> > I'd like to suggest to the Committee that they use
> > identifiers as short as possible for future additions to the
> > standard. I like names such as:

> > pow
> > memcpy
> > fmod
> > qsort
> > strlen
> > puts
> > malloc

> These indentifiers are short because the classic C standard
> requires all global identifiers to be distinguishable using
> their initial 6 characters, case insensitive. In order to
> comply with the standard and to make this rule express and
> instantly visible, the standard C library implementors chose
> to make this rule explicit by limiting the length of those
> identifiers to 6 letters lowercase. It is not obeyed
> consistently, e.g. "memmove" is equivalent to "memmov", but
> you have the idea.

memmove was added much, much later.

I suspect that much of C's terseness can be traced back to the
fact that when C was being invented, the usual terminal was a
teletype. And if you've ever been in a room where a teletype is
at work, you can understand why the less characters, the better.
(This isn't to say that the linker issue wasn't also a
consideration.)

By the time C was being standardized, teletypes were already on
their way out, and software engineering issues were beginning to
be understood. The functions added during standardization
generally are not so restricted by the length of names (but
existing conventions were followed where they were established).

Of course, all this is well over fifteen years ago---twenty or
more for the teletypes. Locking a language into these
restrictions today is certainly not a good idea.

> > In the current Standard, I particularly think the new-style
> > casts are monstrosities:

> > static_cast
> > dynamic_cast
> > reinterpret_cast

> > They take up a disproportionate amount of horizontal
> > screenspace, and are a lot less pleasant to have to type out
> > (particularly "reinterpret_cast").

> > I would prefer the likes of:
> >
> > alignof
> >
> > instead of:
> >
> > alignment_of

> > Of course, this is just my own opinion, and others' opinions
> > may differ... but nonetheless I'd like to throw in my two
> > cents.

> The identifiers printf and memcpy are "monstrosities" for
> every C language student. Without knowing 6 character rule
> sparing one character from memcopy is inexplicable. It gives
> no advantage in typing and makes the name unreadable. And why
> did not they choose the identifier "memmve" as well? The
> abbreviations are inconsistent and hard to learn.

It depends. When there is a large set of functions, working
together, like the str... functions, the abbreviation works.
Otherwise, of course, no.

> On the other hand, nothing prevents you from #defining scast,
> dcast, rcast, alignof and using them in your code. However,
> be warned that coining abbreviations for casts is deprecated

Disparaged, not deprecated. The preprocessor is not going to be
removed from the language.

Using the preprocessor to change the language, in general, is
disparaged.

--
James Kanze GABI Software
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

Frederick Gotham

unread,
Jul 12, 2006, 3:38:29 PM7/12/06
to
Keith Thompson posted:

> Most of the casts I've seen that are "necessary to suppress compiler
> warnings" are actually unnecessary; rather than fixing errors, they
> mask them. I'm not necessarily suggesting that that's the case with
> *your* casts, but I'd be interested in seeing examples where such
> casts are necessary and useful.


Gladly.

Let's say we have a 64-Bit unsigned integer to store the Gross Domestic
Product of the USA for a given year. The units are US dollars:

unsigned long long const gdp = 12485725486486764U;

We also have a 64-Bit unsigned integer to store the population of the USA for
a given year. The units are humans:

unsigned long long const population = 297279178249U;

Now let's say we have a 16-Bit unsigned integer to store the Gross Domestic
Product per capita for a given year. The units are US dollars:

unsigned gdp_per_capita = (unsigned)(gdp / population);


--

Frederick Gotham

Pete Becker

unread,
Jul 12, 2006, 3:45:34 PM7/12/06
to
James Dennett wrote:
> Frederick Gotham wrote:
>
>> posted:
>>
>>
>>> Therefore, the explicit cast operators were deliberately made long and
>>> unwieldy, to discourage the unnecessary and inappropriate use of casts,
>>> and to make it easier to locate them when they are used.
>>
>>
>>
>> I really don't understand this reasoning.
>
>
> It helps to reduce defect densities.
>

Yup. If you rewrite a piece of code and replace all identifiers with
longer ones, you've got fewer defects per character. (Sorry, couldn't
resist.)

Bronek Kozicki

unread,
Jul 12, 2006, 5:18:46 PM7/12/06
to
Frederick Gotham wrote:
> A high-quality programming language like C++ should be designed for expert
> programmers, not for people learning to program.

mistake. Literally everyone programming in some language is, at some stage,
just a person "learning the language". Language that is too difficult to learn
will quickly become niche language, and (I guess) most people here do not want
that.


B.

Pavel Vozenilek

unread,
Jul 12, 2006, 6:10:20 PM7/12/06
to

"Pete Becker" wrote:

>> [longer identifiers] helps to reduce defect densities.


>>
>
> Yup. If you rewrite a piece of code and replace all identifiers with
> longer ones, you've got fewer defects per character. (Sorry, couldn't
> resist.)
>

A very deep collection of scholar studies and recommendations about
identifiers can be found in book "The New C Standard" by Derek M. Jones
(online http://www.knosof.co.uk/cbook/cbook.html), chapter 6.4.2.1.

Influence of identifier length on error rates is covered here as well.

/Pavel

Keith Thompson

unread,
Jul 12, 2006, 7:53:30 PM7/12/06
to
fgot...@SPAM.com (Frederick Gotham) writes:
> Keith Thompson posted:
>> Most of the casts I've seen that are "necessary to suppress compiler
>> warnings" are actually unnecessary; rather than fixing errors, they
>> mask them. I'm not necessarily suggesting that that's the case with
>> *your* casts, but I'd be interested in seeing examples where such
>> casts are necessary and useful.
>
> Gladly.
>
> Let's say we have a 64-Bit unsigned integer to store the Gross Domestic
> Product of the USA for a given year. The units are US dollars:
>
> unsigned long long const gdp = 12485725486486764U;
>
> We also have a 64-Bit unsigned integer to store the population of
> the USA for a given year. The units are humans:
>
> unsigned long long const population = 297279178249U;

Last I heard, the C++ standard doesn't support long long or unsigned
long long (though I understand that's likely to change).

> Now let's say we have a 16-Bit unsigned integer to store the Gross Domestic
> Product per capita for a given year. The units are US dollars:
>
> unsigned gdp_per_capita = (unsigned)(gdp / population);

(unsigned int is *at least* 16 bits, of course, but it happens that
the result, 42000, is guaranteed to fit in an unsigned int.)

What warning does the cast inhibit? I don't get a warning with or
without the cast. (I do get warnings on the literals, depending on
command-line options.) The cast specifies an explicit conversion;
without it, there's still an implicit conversion. There's no obvious
reason why adding or removing the cast should affect whether there's a
warning.

There are a few cases where casts are appropriate. Certain mixed
arithmetic expressions, where you need to override the default
conversions, are one example. Your code above, where you use a cast
to specify a conversion that would have happened implicitly anyway, is
not, IMHO, a good example.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.

---

Steve Clamage

unread,
Jul 13, 2006, 12:23:09 AM7/13/06
to
Keith Thompson wrote:

> fgot...@SPAM.com (Frederick Gotham) writes:
>
>>
>> unsigned long long const gdp = 12485725486486764U;

>> ...


>> unsigned long long const population = 297279178249U;

>> ...


>>
>> unsigned gdp_per_capita = (unsigned)(gdp / population);
>

> What warning does the cast inhibit?

Some compilers warn about implicit "narrowing" conversions, sometimes by
default, sometimes as an option. Such warnings are reasonable, because
narrowing conversions can turn data into trash. Explicit conversions
(using a cast) get no warning.

A major problem with such warnings is that many of the <stdio.h>
functions (for example) return char values in an int, so as to be able
to return EOF to indicate error. Perfectly safe code like this
char ch;
while( (int c=getc()) != EOF ) {
ch = c; // implicit narrowing conversion
...
}
is subject to a warning. Programmers don't want warnings about safe
code, and insert casts to eliminate the warnings.

But the cast, as many have noted, is generally not a good idea. In the
original example, you might later decide that gdp_per_capita ought to be
a larger type. When (as in real code) the various declarations are
spread far apart, you might not realize that the cast no longer matches
the target type. You could wind up with an explicit narrowing conversion
that changes the value, but without the possibility of a compiler warning.

In my example, you might change from using char to using wchar_t or
char16_t, and forget to change the cast in
ch = (char)c; // oops!
If you used new-style casts (e.g. static_cast) instead of a C-style
cast, you could at least grep for casts in your code from time to time
to evaluate whether they are still correct.

In general, I tend toward the view that casts are the wrong answer. The
new-style casts were deliberately given long and distinctive names so
that they stand out -- any cast is potentially dangerous. In the
original example, I would look more closely at whether I need to use
different types, and whether I can isolate casts to one module that
addresses portability issues.

---
Steve Clamage, stephen...@sun.com

Ron Natalie

unread,
Jul 13, 2006, 3:07:34 AM7/13/06
to
kuy...@wizard.net wrote:

> The fundamental problem with short identifiers is that they are
> popular, for precisely the reasons you give. As a result, the shorter
> and more reasonabley a keyword is, the more likely it is to clash with
> a name already in use by existing code. Namespaces reduce this problem,
> but for unqualified names, they do not eliminate it.

It doesn't help for things like the cast operators and aligment_of which
are not NAMES but reserved words in the language.

>
> The *_cast operators are a special case, however. Most conversions that
> don't occur implicitly are dangerous, at least in some contexts.
> Therefore, the explicit cast operators were deliberately made long and
> unwieldy, to discourage the unnecessary and inappropriate use of casts,
> and to make it easier to locate them when they are used.
>

Well that's a stupid reason. Actually it is to be encouraged to use
the C++-style casts over the SHORTER AND EASIER TO TYPE C-STYLE ONES
as it limits the range of possible conversions done by any one operator.

Frederick Gotham

unread,
Jul 13, 2006, 10:31:47 AM7/13/06
to
Keith Thompson posted:

> What warning does the cast inhibit? I don't get a warning with or
> without the cast. (I do get warnings on the literals, depending on
> command-line options.) The cast specifies an explicit conversion;
> without it, there's still an implicit conversion. There's no obvious
> reason why adding or removing the cast should affect whether there's a
> warning.


Most -- if not all -- C++ compilers warn about implicit conversions from wider
types to narrower types, e.g.:

(Let's pretend I initialise them first:

float a; double b; a = b;
int a; long b; a = b;
char a; short b; a = b;


Warnings can be a right pain in the neck when it comes to C++ programming,
which is why I recently started a thread entitled "Deliberately Supress
Warnings" on this newsgroup.

Another common warning is arithmetic between signed and unsigned types.


--

Frederick Gotham

Krzysztof Zelechowski

unread,
Jul 13, 2006, 10:32:29 AM7/13/06
to

Uzytkownik "kanze" <ka...@gabi-soft.fr> napisal w wiadomosci
news:1152708021.5...@m79g2000cwm.googlegroups.com...

>
> Disparaged, not deprecated. The preprocessor is not going to be
> removed from the language.
>
> Using the preprocessor to change the language, in general, is
> disparaged.
>
> --

Thanks. The abundance of your English vocabulary keeps amazing me all the
time.
Chris

Krzysztof Zelechowski

unread,
Jul 13, 2006, 10:33:17 AM7/13/06
to

Uzytkownik "Ron Natalie" <r...@spamcop.net> napisal w wiadomosci
news:44b5db20$0$18490$9a6e...@news.newshosting.com...

> kuy...@wizard.net wrote:
>
>> The *_cast operators are a special case, however. Most conversions that
>> don't occur implicitly are dangerous, at least in some contexts.
>> Therefore, the explicit cast operators were deliberately made long and
>> unwieldy, to discourage the unnecessary and inappropriate use of casts,
>> and to make it easier to locate them when they are used.
>>
> Well that's a stupid reason. Actually it is to be encouraged to use
> the C++-style casts over the SHORTER AND EASIER TO TYPE C-STYLE ONES
> as it limits the range of possible conversions done by any one operator.
>

(cast)s should not pass the code review at all. The developer who uses them
in C++ code will have to correct them. This will stop him from taking
shortcuts in the future.
They cannot be eliminated from the language but the compiler could issue a
warning. Mine does not, alas.
Chris

Seungbeom Kim

unread,
Jul 13, 2006, 12:40:32 PM7/13/06
to
Ron Natalie wrote:

> kuy...@wizard.net wrote:
>>
>> The *_cast operators are a special case, however. Most conversions that
>> don't occur implicitly are dangerous, at least in some contexts.
>> Therefore, the explicit cast operators were deliberately made long and
>> unwieldy, to discourage the unnecessary and inappropriate use of casts,
>> and to make it easier to locate them when they are used.
>>
> Well that's a stupid reason. Actually it is to be encouraged to use
> the C++-style casts over the SHORTER AND EASIER TO TYPE C-STYLE ONES
> as it limits the range of possible conversions done by any one operator.

Of course, it's best to stay away from all kind of casts if possible,
but the general advice is to use only C++-style casts and to avoid the
old C-style casts (even though the latter may seem tempting) *when casts
can be justified* -- after all, they're there because we do need them --
so that they can stand out and keep you alert to the possible danger.
The g++ option "-Wold-style-cast" can help you with this.

--
Seungbeom Kim

kuy...@wizard.net

unread,
Jul 13, 2006, 2:16:21 PM7/13/06
to
Ron Natalie wrote:
> kuy...@wizard.net wrote:
>
> > The fundamental problem with short identifiers is that they are
> > popular, for precisely the reasons you give. As a result, the shorter
> > and more reasonabley a keyword is, the more likely it is to clash with
> > a name already in use by existing code. Namespaces reduce this problem,
> > but for unqualified names, they do not eliminate it.
>
> It doesn't help for things like the cast operators and aligment_of which
> are not NAMES but reserved words in the language.

I'm not quite sure what you mean by that comment. The cast operators
and the proposed alignment_of are keywords, which are names with a
special meaning to the compiler. Reserved identifiers include all of
those keywords, plus all of the standard-defined names which are part
of the C++ standard library.
Previously user-defined names and new keywords are quite capable of
interfering with each other. Using namespaces for user-defined names
removes the conflicts, but only insofar as those names are used with
namespace prefixes. Making the names longer helps reduce the liklihood
of conflict, without actually removing it, for both user-defined names
and keywords

> > The *_cast operators are a special case, however. Most conversions that
> > don't occur implicitly are dangerous, at least in some contexts.
> > Therefore, the explicit cast operators were deliberately made long and
> > unwieldy, to discourage the unnecessary and inappropriate use of casts,
> > and to make it easier to locate them when they are used.
> >
> Well that's a stupid reason. Actually it is to be encouraged to use
> the C++-style casts over the SHORTER AND EASIER TO TYPE C-STYLE ONES
> as it limits the range of possible conversions done by any one operator.

Wise programmers see the limited range of possible conversions as an
advantage, not a disadvantage. It gives you more precise control over
what is happening, and allows for better error messages when you're not
doing what you think you're doing.

The fact that many programmers are not wise is a problem not easily
solved. There is, unfortunately, nothing that could be done to render
the C-style casts illegal without breaking backward compatibility with
C. The most that can be done is to prohibit them in new code, except in
those rare occasions where they do something that can't be done with
the new cast, as a matter of programming guidelines external to the
standard.

Seungbeom Kim

unread,
Jul 13, 2006, 2:25:37 PM7/13/06
to
Steve Clamage wrote:
> Keith Thompson wrote:
>> fgot...@SPAM.com (Frederick Gotham) writes:
>>>
>>> unsigned long long const gdp = 12485725486486764U;
>>> ...
>>> unsigned long long const population = 297279178249U;
>>> ...
>>>
>>> unsigned gdp_per_capita = (unsigned)(gdp / population);
>
> But the cast, as many have noted, is generally not a good idea. In the
> original example, you might later decide that gdp_per_capita ought to be
> a larger type. When (as in real code) the various declarations are
> spread far apart, you might not realize that the cast no longer matches
> the target type. You could wind up with an explicit narrowing conversion
> that changes the value, but without the possibility of a compiler warning.

A safer option is to use boost::numeric_cast, which checks whether
the value can be preserved in the target type and throws an exception
otherwise.

In fact, I would also like a version in which a similar checking is done
only in debug builds, à la boost::polymorphic_downcast: i.e.

template <class Target, class Source>
inline Target numeric_cast(Source x)
{
assert( x is in the range of Target );
return static_cast<Target>(x);
}

(I'm not sure how to express in C++ what I wrote inside assert( );
when I look into the implementation of boost::numeric::converter,
it seems too complicated for me to understand in a short time.)

--
Seungbeom Kim

Frederick Gotham

unread,
Jul 13, 2006, 6:21:05 PM7/13/06
to
Seungbeom Kim posted:


> template <class Target, class Source>
> inline Target numeric_cast(Source x)
> {
> assert( x is in the range of Target );
> return static_cast<Target>(x);
> }
>
> (I'm not sure how to express in C++ what I wrote inside assert( );


assert( numeric_limits<Target>::max() >= x );

--

Frederick Gotham

Greg Herlihy

unread,
Jul 14, 2006, 2:41:13 AM7/14/06
to

kuy...@wizard.net wrote:
> Ron Natalie wrote:
> > kuy...@wizard.net wrote:
> >
> > > The fundamental problem with short identifiers is that they are
> > > popular, for precisely the reasons you give. As a result, the shorter
> > > and more reasonabley a keyword is, the more likely it is to clash with
> > > a name already in use by existing code. Namespaces reduce this problem,
> > > but for unqualified names, they do not eliminate it.
> >
> > It doesn't help for things like the cast operators and aligment_of which
> > are not NAMES but reserved words in the language.
>
> I'm not quite sure what you mean by that comment. The cast operators
> and the proposed alignment_of are keywords, which are names with a
> special meaning to the compiler. Reserved identifiers include all of
> those keywords, plus all of the standard-defined names which are part
> of the C++ standard library.
> Previously user-defined names and new keywords are quite capable of
> interfering with each other. Using namespaces for user-defined names
> removes the conflicts, but only insofar as those names are used with
> namespace prefixes. Making the names longer helps reduce the liklihood
> of conflict, without actually removing it, for both user-defined names
> and keywords

It is not possible to resolve a conflict between a user-defined name
and a keyword without changing the user-defined name. Placing the
user-defined name in namespace or qualifying it with the name of a
namespace is of no help in resolving the conflict - a keyword is
recognized as a keyword "unconditionally". For that reason, many
language proposals tend to be reticent when it comes to proposing new
keywords to the C++ language - because any conflicts created by a new
keyword with a user-defined name is not one that could have been
foreseen and avoided.

Greg

SuperKoko

unread,
Jul 14, 2006, 12:45:48 PM7/14/06
to

Frederick Gotham wrote:
> Keith Thompson posted:
>
> > Most of the casts I've seen that are "necessary to suppress compiler
> > warnings" are actually unnecessary; rather than fixing errors, they
> > mask them. I'm not necessarily suggesting that that's the case with
> > *your* casts, but I'd be interested in seeing examples where such
> > casts are necessary and useful.
>
>
> Gladly.
>
> Let's say we have a 64-Bit unsigned integer to store the Gross Domestic
> Product of the USA for a given year. The units are US dollars:
>
> unsigned long long const gdp = 12485725486486764U;
>
> We also have a 64-Bit unsigned integer to store the population of the USA for
> a given year. The units are humans:
>
> unsigned long long const population = 297279178249U;
>
> Now let's say we have a 16-Bit unsigned integer to store the Gross Domestic
> Product per capita for a given year. The units are US dollars:
>
> unsigned gdp_per_capita = (unsigned)(gdp / population);
>
>
Using a C-style cast here is a bad idea, because C++ style cast are far
easier to search for (with grep or with any good text editor).
And, since a C++ program contains very few reinterpret_cast, it can be
very easy to port a C++ program, searching for all reinterpret_cast and
changing these non-portable constructs, or at least checking that they
work as expected on the new platform.

Here, even static_cast is not a very good idea.
You can use this template, though:

template <class TDestination, class TSource>
inline TDestination implicit_cast(const TSource& source) {
return source;
}

The name looks like an oxymoron... But I have not found any better
name.

Of course, if you like terseness, you can name it "icast" or "imcst" or
"icst"

James Dennett wrote:
> Frederick Gotham wrote:

> > A high-quality programming language like C++ should be designed for expert
> > programmers, not for people learning to program.
>
>

> I think that C++ should recognize that its user base includes
> people at various levels of expertise, from some of the experts
> who inhabit forums such as csc++ through good professional
> programmers, average professional programmers, weak professional
> programmers, hobbyists, and people who use C++ as a tool
> incidental to their primary line of work.
>

Yes, but only only advanced programmers who know what they are doing
and the rationale behind each cast actually use the C++-style casts :
Most beginners, students and occasionals C++ programmers use C-style
cast!

I think that C++-style casts have long names because:
1) It avoids potential name clashes with legacy code.
2) No abbreviation, means that it is easier for a beginner to spell it
right from the start.
Abbreviations are inconsistent and must be actively learnt.

Frederick Gotham wrote:
> static_cast
> dynamic_cast
> reinterpret_cast
>
>

> They take up a disproportionate amount of horizontal screen space, and are a


> lot less pleasant to have to type out (particularly "reinterpret_cast").

If you want to avoid typing in these "long" names you can use a
Good(TM) text editor such as Vim, add these lines

iabbrev scst static_cast
iabbrev dcst dynamic_cast
iabbrev rcst reinterpret_cast

In your .vimrc file or in an autocmd script loaded for C++ files.

1) You will not have to type the full names.
2) But your code will still be readable by any normal human being since
it will contain the expanded forms : static_cast & co.

For the horizontal screen space, you can put carriage returns after
each token, or use \<NEWLINE> inside any token.

kuy...@wizard.net wrote:
> Therefore, the explicit cast operators were deliberately made long and
> unwieldy, to discourage the unnecessary and inappropriate use of casts,
> and to make it easier to locate them when they are used.

I don't think so, even if it is in the FAQ of Bjarne Stroustrup's
homepage. I think it is more a joke on a side effect of this WG21's
choice.

IMHO, C++ mustn't (and actually *does not*, personally I type fast
enough on my keyboard to feel comfortable with reinterpret_cast) impose
a style, even if it allows bad programming styles. C++ gives to the
programmer the most freedom it can.

The C philosophy said: "Trust the programmer".
IMHO, the C++ philosophy is more like : "Trust the programmer when he
is explicit about his intents, and warn him when he does something that
he might not want to do". But C++ must not discourage the programmer
from doing what he wants.

In that sense, explicit casts are a C++ gift.
But a programmer is not more explicit when he writes reinterpret_cast
than reincast. In both cases, he knows what he does.
C-style casts are less "explicit", for two reasons:
1) Main reason : they have a large number of functions with only one
syntax while C++-style casts have more forms.
2) C-style casts are less easily visible for a code reader because they
are hidden behind a terse syntax, without any explicit keyword.
Don't forget that, a C programmer, even if he knows what he does when
he uses an explicit cast, might find uncomfortable point (2). Because
he will have to re-read his code, and maintain it.
So, being "explicit", is both a matter of "writing explicitly" and a
matter of "visibility when reading".

IMHO, C++ style casts have these 3 functions.
1) Accuracy of the cast (unlike C casts which are very large).
2) Being explicit when writing the code (arguably C-style casts share
that point too).
3) Being well-visible when reading the code.

I don't think that C++-style casts have any other function (such as
discouraging their usage).

Verbosity is not a problem for most people (Java is quite popular
though it is verbose).
Most people have no problem with that, and feel even more comfortable
with verbose identifiers than with terse UNIX/C/Perl-style
one-to-six-characters identifiers.

I admit that personally, I feel comfortable with short identifiers for
builtin language constructs (as in Perl), but I have no problem with
long identifiers.

James Kanze

unread,
Jul 14, 2006, 3:28:00 PM7/14/06
to
James Dennett wrote:
> Frederick Gotham wrote:
>> posted:

>>> Therefore, the explicit cast operators were deliberately
>>> made long and unwieldy, to discourage the unnecessary and
>>> inappropriate use of casts, and to make it easier to locate
>>> them when they are used.

>> I really don't understand this reasoning.

> It helps to reduce defect densities.

>> A high-quality programming language like C++ should be
>> designed for expert programmers, not for people learning to
>> program.

> I think that C++ should recognize that its user base includes
> people at various levels of expertise, from some of the experts
> who inhabit forums such as csc++ through good professional
> programmers, average professional programmers, weak professional
> programmers, hobbyists, and people who use C++ as a tool
> incidental to their primary line of work.

Realistically, if C++ can only be used by language experts, then
it won't be used at all. In most projects, most of the experts
are domain experts; it's not unusual for me to be the only
technical expert for several projects at a time.

One of the things I've see with real experts is that they
realize that not everyone can, or should be a language expert,
and they use the language accordingly. And while a non-expert
may not be able to come up with some of the things they do, a
non-expert will be able to understand them.

>> There's plenty of alternatives out there for the not-so-apt:
>> Visual Basic, Java.

>> No expert programmer would use a cast unnecessarily, e.g.:

>> int i;

>> long j = (long)i; /* or static_cast if you prefer */

> Innumerable bugs in code written by professionals have been
> caused by casts that should not have been present.

It's interesting to note that the author of those lines actually
posted such an error in comp.lang.c++.moderated a day or two
ago:-). A nice little pointer cast which will provoke a core
dump under certain conditions on my machine (a Sun
Sparc---hardly an exotic platform, unless you consider anything
but a PC exotic). As a solution to a problem where I don't use
a cast.

--
James Kanze kanze...@neuf.fr


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

Frederick Gotham

unread,
Jul 15, 2006, 12:28:33 AM7/15/06
to
James Kanze posted:


> It's interesting to note that the author of those lines actually
> posted such an error in comp.lang.c++.moderated a day or two
> ago:-). A nice little pointer cast which will provoke a core
> dump under certain conditions on my machine (a Sun
> Sparc---hardly an exotic platform, unless you consider anything
> but a PC exotic). As a solution to a problem where I don't use
> a cast.


Are you referring to the code in which I assume that the char[sizeof(int)]
array is suitably aligned?


http://groups.google.ie/group/comp.lang.c++.moderated/browse_frm/thread/fe5cc
7fe957d113b/f744078a86d33fbc?lnk=st&q=alignment+group%3Acomp.lang.c%2B%
2B.moderated+author%3AFrederick+author%3AGotham&rnum=1&hl=en#f744078a86d33fbc


Are you saying that, on your system, the code crashes if the char array isn't
suitably aligned?

--

Frederick Gotham

bjarne

unread,
Jul 15, 2006, 1:52:36 AM7/15/06
to

SuperKoko wrote:
>
> kuy...@wizard.net wrote:
> > Therefore, the explicit cast operators were deliberately made long and
> > unwieldy, to discourage the unnecessary and inappropriate use of casts,
> > and to make it easier to locate them when they are used.
>
> I don't think so, even if it is in the FAQ of Bjarne Stroustrup's
> homepage. I think it is more a joke on a side effect of this WG21's
> choice.

It is not a joke:
http://www.research.att.com/~bs/bs_faq2.html#static-cast
You can find equivalent comments in D&E.
That reason was mentioned in committee emails long before the design
was finalized.

-- Bjarne Stroustrup; http://www.research.att.com/~bs

Krzysztof Zelechowski

unread,
Jul 15, 2006, 8:41:50 AM7/15/06
to
assert(Target(x) == x);

Uzytkownik "Seungbeom Kim" <musi...@bawi.org> napisal w wiadomosci
news:e94rko$92e$1...@news.Stanford.EDU...

In fact, I would also like a version in which a similar checking is done

only in debug builds, ą la boost::polymorphic_downcast: i.e.

template <class Target, class Source>
inline Target numeric_cast(Source x)
{
assert( x is in the range of Target );
return static_cast<Target>(x);
}

(I'm not sure how to express in C++ what I wrote inside assert( );
when I look into the implementation of boost::numeric::converter,
it seems too complicated for me to understand in a short time.)

---

kanze

unread,
Jul 17, 2006, 10:59:54 AM7/17/06
to
"Krzysztof Zelechowski" wrote:
> assert(Target(x) == x);

You may get an implementation defined signal before the assert
trips (which probably doesn't matter). You may also fail to
trip even when you should, if the conversion is between signed
and unsigned types, e.g. Target is unsigned int, Source is int,
and the value of x is -3.

--
James Kanze GABI Software

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

kanze

unread,
Jul 17, 2006, 11:00:27 AM7/17/06
to
Frederick Gotham wrote:
> Seungbeom Kim posted:

> > template <class Target, class Source>
> > inline Target numeric_cast(Source x)
> > {
> > assert( x is in the range of Target );
> > return static_cast<Target>(x);
> > }

> > (I'm not sure how to express in C++ what I wrote inside assert( );

> assert( numeric_limits<Target>::max() >= x );

assert( std::numeric_limits< Target >::max() >= x
&& (! std::numeric_limits< Target >::is_signed
|| (std::numeric_limits< Target >::is_integer
? std::numeric_limits< Target >::min() >= x
: -std::numeric_limits< Target >::max() >= x)) )
;

If you want to be really general, you might want to throw in a
check for is_bounded (if is_bounded false, max() and min() are
not significant), and maybe is_specialized as well.

Since is_signed, is_integer, is_bounded and is_specialized are
all constant integral expressions (of type bool), you can
probably use some very simple template metaprogramming to make
the code more readable.

--
James Kanze GABI Software
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

ThosRTanner

unread,
Jul 17, 2006, 11:01:50 AM7/17/06
to

Frederick Gotham wrote:
> posted:

>
>
> > Therefore, the explicit cast operators were deliberately made long and
> > unwieldy, to discourage the unnecessary and inappropriate use of casts,
> > and to make it easier to locate them when they are used.
>
>
> I really don't understand this reasoning.
>
> A high-quality programming language like C++ should be designed for expert
> programmers, not for people learning to program. There's plenty of

> alternatives out there for the not-so-apt: Visual Basic, Java.

Is this a troll? Although I'd agree that there are a lot of cowboy
programmers out there who have apalling design and coding practices, in
the same way that there are cowboy builders, plumbers, ..., I think you
will find that expert C++ programmers get that way from learning the
language, they aren't born knowing the ins and outs of C++ programmers.

In general however, a language that is designed to make it difficult to
make mistakes and make it easy to spot where mistakes are likely is
infinitely preferable over the other. This is why high level languages
are preferable to assembly code - which in turn is prefereable to
programming the machine in hex codes.

There are areas where C++ is NOT friendly to the novice, and causes
grief and pain - this is why coding standards evolve.

> No expert programmer would use a cast unnecessarily, e.g.:
>
> int i;
>
> long j = (long)i; /* or static_cast if you prefer */
>
>

> And who's to say if a cast is "inappropriate"... ?

Or indeed necessary

> C was built on a foundation of programmers who are competent, not on
> holding the hands of beginners who aren't out of diapers yet. C++ should
> build on this proud mentality.

I have no doubt it is a proud mentality. Whether it is a mentality that
makes things better for others is rather open to question.

> My efficient, fully-portable, Standard-compliant code contains many casts.

> Some are necessary to make the code compile. Some are necessary to suppress


> compiler warnings. But they're all there for a reason!

And all are somewhat dangerous.

> Why should expert programmers be burdened with unwieldy names? It insults
> human intelligence.

I'd find it pretty difficult to insult that level of intelligence.

>
> Some may hold in derision my use of old-style casts, but I'll definitely
> prefer:
>
> int *pi = (int*)pc;
>
> over:
>
> int *pi = reinterpret_cast<int*>(const_cast<char*>(pc));
>

More fool you for using either of them. But at least the 2nd is
flagging to the tired eye that something pretty damn dangerous is going
on.

kanze

unread,
Jul 17, 2006, 11:38:38 AM7/17/06
to
Frederick Gotham wrote:
> James Kanze posted:

> > It's interesting to note that the author of those lines
> > actually posted such an error in comp.lang.c++.moderated a
> > day or two ago:-). A nice little pointer cast which will
> > provoke a core dump under certain conditions on my machine
> > (a Sun Sparc---hardly an exotic platform, unless you
> > consider anything but a PC exotic). As a solution to a
> > problem where I don't use a cast.

> Are you referring to the code in which I assume that the
> char[sizeof(int)] array is suitably aligned?

Yes.

> http://groups.google.ie/group/comp.lang.c++.moderated/browse_frm/thread/fe5cc
> 7fe957d113b/f744078a86d33fbc?lnk=st&q=alignment+group%3Acomp.lang.c%2B%
> 2B.moderated+author%3AFrederick+author%3AGotham&rnum=1&hl=en#f744078a86d33fbc

> Are you saying that, on your system, the code crashes if the
> char array isn't suitably aligned?

On my Sun Sparc, yes. On most non-Intel based systems, in fact.
On some word adressed machines, it will not crash, but will
simply access the wrong bytes. The bits which select the byte
in the word are simply ignored for word accesses.

The point, of course, is simply to point out that even the
experts DO make mistakes. Code should not be designed to be
read-only, since someone has to fix those mistakes (and even
without the mistakes, the code may have to evolve). There are
some exceptions, but generally, code will be read many more
times than it will be written. We, and the language, should
thus favor the reader. (If typing long names is a problem, my
editor supports abbreviations, so that each time you enter an
identifier rc, the editor will replace it on the fly with
reinterpret_cast. But IMHO, if you're using reinterpret_cast
often enough for typing time to be a problem, you're using it
far too often.

--
James Kanze GABI Software

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

Pete Becker

unread,
Jul 17, 2006, 12:25:23 PM7/17/06
to
ThosRTanner wrote:
>
> In general however, a language that is designed to make it difficult to
> make mistakes and make it easy to spot where mistakes are likely is
> infinitely preferable over the other.

Hence the stunning success of Pascal. <g>

Frederick Gotham

unread,
Jul 17, 2006, 2:16:45 PM7/17/06
to
ThosRTanner posted:

> Is this a troll?


Great way to start a conversation -- congratulations on the social skills.


> Although I'd agree that there are a lot of cowboy programmers out there
> who have apalling design and coding practices, in the same way that
> there are cowboy builders, plumbers, ..., I think you will find that
> expert C++ programmers get that way from learning the language, they
> aren't born knowing the ins and outs of C++ programmers.


The same can be said for any pursuit.

A boxer shouldn't expect to win a title within his first month of training.

A plumber shouldn't expect to be the best plumber in the city after his
first month of training.

A surgeon shouldn't expect to be top surgeon in his practice within his
first month.

A programmer shouldn't expect to be the best programmer in the world after
his first month.

Practise makes perfect -- programming is no exception.


> In general however, a language that is designed to make it difficult to
> make mistakes and make it easy to spot where mistakes are likely is
> infinitely preferable over the other. This is why high level languages
> are preferable to assembly code - which in turn is prefereable to
> programming the machine in hex codes.


Yes, but how dumb do you want to go? C++ dumb, or Java dumb?


> There are areas where C++ is NOT friendly to the novice, and causes
> grief and pain - this is why coding standards evolve.


Just because something is difficult at the start doesn't mean you should
give up.

Learning to walk is hard. Learning to talk is hard. Learning to throw a
ball is hard. Learning to read is hard. Learning to write is hard. Learning
to perform a heart transplant is hard.


>> And who's to say if a cast is "inappropriate"... ?
>
> Or indeed necessary


You either get a compile error or you don't.


>> C was built on a foundation of programmers who are competent, not on
>> holding the hands of beginners who aren't out of diapers yet. C++
>> should build on this proud mentality.
>
> I have no doubt it is a proud mentality. Whether it is a mentality that
> makes things better for others is rather open to question.


I was able to learn C++. You were able to learn C++.

I may have above average intelligence, but I'm no genius -- yet still I can
program proficiently.


>> My efficient, fully-portable, Standard-compliant code contains many
>> casts. Some are necessary to make the code compile. Some are necessary
>> to suppress compiler warnings. But they're all there for a reason!
> And all are somewhat dangerous.


No more dangerous than eating fish. Watch for bones and you'll have no
problem.

Of course, if you don't watch for bones, then it's your own problem.


>> Why should expert programmers be burdened with unwieldy names? It
>> insults human intelligence.
> I'd find it pretty difficult to insult that level of intelligence.


There are people in my college who employ use of a calculator to add two
single-digit numbers.


>> Some may hold in derision my use of old-style casts, but I'll
>> definitely prefer:
>>
>> int *pi = (int*)pc;
>>
>> over:
>>
>> int *pi = reinterpret_cast<int*>(const_cast<char*>(pc));
>>
> More fool you for using either of them. But at least the 2nd is
> flagging to the tired eye that something pretty damn dangerous is going
> on.


Again the argument of "unnecessary" or "inappropriate" casts. This is
ludicrous! Only very poor programmers mis-use casts. Since when do we
accommodate the very poor programmers?

And again we have melodramatic use of "dangerous". There's nothing wrong
with the way I use casts. Here's some code of mine which makes brilliant
use of the feature known as casts. The code's objective is to increment a
pointer by a specified number of bytes. Please let me know where you feel
the danger lies:

#include <cstddef>

template<class T>
inline void AdvPtr( T *&p, std::size_t const bytes )
{
p = reinterpret_cast<T*>(
const_cast<char*>(
reinterpret_cast<char const*>(p) + bytes
)
);
}


--

Frederick Gotham

Steve Clamage

unread,
Jul 17, 2006, 2:10:24 PM7/17/06
to
Pete Becker wrote:

> ThosRTanner wrote:
>
>>
>> In general however, a language that is designed to make it difficult to
>> make mistakes and make it easy to spot where mistakes are likely is
>> infinitely preferable over the other.
>
>
> Hence the stunning success of Pascal. <g>

I'm sure Pete would agree that the strong typeing of Pascal was not the
primary reason for Pascal failing to become a popular and successful
development language.

I think the primary reason was the lack of facilities for large- (or
even medium-) scale programming. (Brian Kernighan's views
notwithstanding:
http://www.cs.virginia.edu/~evans/cs655-S00/readings/bwk-on-pascal.html )

1. Standard Pascal did not allow separate compilation or user-defined
libraries. Each real-world Pascal implementation provided the facility
in some way, different for each compiler.

2. Standard Pascal forced a strict order on declarations, and had no
facility for including headers. (If header inclusion were allowed, you
would have had to split a header into pieces to keep the strict
declaration order.) Again, real-world compilers relaxed the strict
ordering rules and allowed header inclusion -- differently for each
compiler. BTW, the reason for the declaration order was to permit
creating a one-pass compiler -- the rules were not inspired by safer
progamming practice.

3. Standard Pascal did not allow ad-hoc creation of pointers. The only
use of a pointer was for heap data, and you could not do pointer
arithmetic. You could not take a pointer to a function, but you could
pass functions as strictly-typed function parameters. Again, real-world
compilers provided ad-hoc pointers and pointer arithmetic, but the
details varied.

The Pascal Committee could not agree on these facilities for real-world
programming, so Standard Pascal wound up with none. The resulting
language turned out to be what some of the Committee members thought all
programmers ought to want, but unfortunately was not what most
programmers actually wanted.

---
Steve Clamage, stephen...@sun.com

Gennaro Prota

unread,
Jul 17, 2006, 3:35:11 PM7/17/06
to
On Tue, 11 Jul 2006 10:32:28 CST, "kanze" <ka...@gabi-soft.fr> wrote:

>There are 32949 legal two character names.

Care to explain the origin of that number?

--
Gennaro Prota

SuperKoko

unread,
Jul 17, 2006, 4:39:10 PM7/17/06
to

Frederick Gotham wrote:
> And again we have melodramatic use of "dangerous". There's nothing wrong
> with the way I use casts. Here's some code of mine which makes brilliant
> use of the feature known as casts. The code's objective is to increment a
> pointer by a specified number of bytes. Please let me know where you feel
> the danger lies:
>
> #include <cstddef>
>
> template<class T>
> inline void AdvPtr( T *&p, std::size_t const bytes )
> {
> p = reinterpret_cast<T*>(
> const_cast<char*>(
> reinterpret_cast<char const*>(p) + bytes
> )
> );
> }
>
>

The const_cast is very inappropriate here.
It should be:


inline void AdvPtr( T *&p, std::size_t const bytes )
{
p = reinterpret_cast<T*>(

reinterpret_cast<char *>(p) + bytes
);
}

Now, I can't see any legitimate usage of this function!

bytes should always be a multiple of sizeof(T)... Otherwise, welcome
into the nigthmare of misalignment.
Worst, actually, reinterpret_casting from a misaligned char* to T* may
well produce a pointer that we don't expect, worst, it might even
produce an unspecified pointer (depends on the implementation-defined
reinterpret_cast to a type with a strictier type alignment).

And, if bytes is always a multiple of sizeof(T), this function can be
written easily as:
inline void AdvPtr(T*& p, std::size_t const bytes) {
p+= (bytes/sizeof(T));
}

But, normally, you should never have this "bytes" offset... It should
be:
inline void AdvPtr(T*& p, std::size_t const index) {
p+=index;
}
Well, it is simply +=


I know that, when programming low level things, it might be useful to
work on "raw" data, and, sometimes there is data mapped inside this raw
data.
In that case, there are only two good types of pointers for working on
this raw data:
character pointers (unsigned char* is prefered) or void*.

And, in that case, it might be legitimate to do things such as:
T* p=static_cast<T*>(my_void_pointer);
Or:
T* p=static_cast<T*>(static_cast<void*>(my_char_pointer+offset));

A reinterpret_cast might be used here, but personally, I prefer two
static_casts (or an implicit_cast followed by a static_cast).
But, such very low level things should be done seldomly... Almost
never.

A more legitimate, and common, reason of using casts is the connection
of a C++ program to a C library, containing callback functions with
void* context parameters.
In that case, static_cast can be used to downcast a void* pointer to a
MyContext*

Pete Becker

unread,
Jul 17, 2006, 3:58:44 PM7/17/06
to
Steve Clamage wrote:
> Pete Becker wrote:
>
>> ThosRTanner wrote:
>>
>>>
>>> In general however, a language that is designed to make it difficult to
>>> make mistakes and make it easy to spot where mistakes are likely is
>>> infinitely preferable over the other.
>>
>>
>>
>> Hence the stunning success of Pascal. <g>
>
>
> I'm sure Pete would agree that the strong typeing of Pascal was not the
> primary reason for Pascal failing to become a popular and successful
> development language.
>

Nevertheless, it is a counterexample to the original assertion. Pascal
code is best written by a team of two programmers: one to write the code
and one to write the semicolons.

Seriously: Pascal is annoying in its attempts to enforce orthodoxy, and
that's separate from the specific problems that Steve mentions. I used
Turbo Pascal for several years. Moving from Pascal to C was a tremendous
relief.

Francis Glassborow

unread,
Jul 17, 2006, 4:34:09 PM7/17/06
to
In article <b8knb2lfciothjm4g...@4ax.com>, Gennaro Prota
<gennar...@yahoo.com> writes

>On Tue, 11 Jul 2006 10:32:28 CST, "kanze" <ka...@gabi-soft.fr> wrote:
>
>>There are 32949 legal two character names.
>
>Care to explain the origin of that number?

Yes definitely an odd number for that claim 523 * 7 * 3 * 3 does not
seem to offer much promise in this context. I think there are 3339 (53 *
63) legal 2 character names in C++ + 53 single character ones.

--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

Frederick Gotham

unread,
Jul 17, 2006, 4:44:12 PM7/17/06
to
SuperKoko posted:

> The const_cast is very inappropriate here.


It's there for a reason.

I don't use unnecessary casts.

I don't use inappropriate casts.


> It should be:
> inline void AdvPtr( T *&p, std::size_t const bytes )
> {
> p = reinterpret_cast<T*>(
> reinterpret_cast<char *>(p) + bytes
> );
> }


My original code works perfectly with:

(1) Pointer to non-const
(2) Pointer to const


Yours is restricted to:

(1) Pointer to non-const


> Worst, actually, reinterpret_casting from a misaligned char*


No such thing as a misaligned char*.


> I know that, when programming low level things, it might be useful to
> work on "raw" data, and, sometimes there is data mapped inside this raw
> data.
> In that case, there are only two good types of pointers for working on
> this raw data:
> character pointers (unsigned char* is prefered) or void*.


unsigned char* would indeed be preferable if you actually access the data at
the specified address.

If you're just doing pointer arithmetic though, there's no need for the
superfluous "unsigned".


> T* p=static_cast<T*>(static_cast<void*>(my_char_pointer+offset));


Ridiculous overkill. (Not to mention it doesn't take care of constness.)


--

Frederick Gotham

Frederick Gotham

unread,
Jul 17, 2006, 5:12:36 PM7/17/06
to
Gennaro Prota posted:

> On Tue, 11 Jul 2006 10:32:28 CST, "kanze" <ka...@gabi-soft.fr> wrote:
>
>>There are 32949 legal two character names.
>
> Care to explain the origin of that number?


I don't think it's correct (although I'm open to correction).


Here's my own calculations:
---------------------------

(1) 26 letters in the English part of the alphabet (i.e. without diacritics).

(2) Each has an uppercase/lowercase form, so that's 52 distinct characters.

Pretend you're dealing with a number system whose radix is 52, and you want
to calculate the greatest value representable in two digits. Then add one.

51(52^1) + 51(52^0) + 1

= 2652 + 51 + 1

= 2704

--

Frederick Gotham

kuy...@wizard.net

unread,
Jul 17, 2006, 9:25:21 PM7/17/06
to
Frederick Gotham wrote:
> ThosRTanner posted:

.
> >> And who's to say if a cast is "inappropriate"... ?
> >
> > Or indeed necessary
>
> You either get a compile error or you don't.

Yes, but that's hardly a useful criterion.

In some cases, the reason why a cast is inappropriate only shows up at
run time. In some cases, it only shows up when you port the code to a
platform with unexpected (but legal) properties. In some cases, the
problem comes up only when someone who's not as familiar with the code
as an idealist would like them to be makes a change to something.
Any one of those characteristics would prevent a compiler error, though
a good compiler will at least issue warnings that help you avoid some
of the possible problems.

> >> C was built on a foundation of programmers who are competent, not on
> >> holding the hands of beginners who aren't out of diapers yet. C++
> >> should build on this proud mentality.
> >
> > I have no doubt it is a proud mentality. Whether it is a mentality that
> > makes things better for others is rather open to question.
>
> I was able to learn C++. You were able to learn C++.

>From your comments, I suspect that you still have a lot to learn, of
the kinds of things that aren't covered by ordinary textbooks.

> I may have above average intelligence, but I'm no genius -- yet still I can
> program proficiently.

The key point isn't whether it's possible to learn to program; the
question is whether it's unnecessarily diffiuclt to learn to program
well. Our economy needs a large number of competent C++ programmers,
far larger than the number of people who can actually learn to become
that competent; most C++ programming is done by people with far less
than perfect knowledge of the C++ language.

Designing the language around the attitude that it need only be
proficiently writeable, or easily readible, by the most competent
programmers, would be a serious mistake.

> >> My efficient, fully-portable, Standard-compliant code contains many
> >> casts. Some are necessary to make the code compile. Some are necessary
> >> to suppress compiler warnings. But they're all there for a reason!
> > And all are somewhat dangerous.
>
> No more dangerous than eating fish. Watch for bones and you'll have no
> problem.
>
> Of course, if you don't watch for bones, then it's your own problem.

That analogy underestimates both the danger, and the difficulty of
avoiding it.

> >> Some may hold in derision my use of old-style casts, but I'll
> >> definitely prefer:
> >>
> >> int *pi = (int*)pc;
> >>
> >> over:
> >>
> >> int *pi = reinterpret_cast<int*>(const_cast<char*>(pc));
> >>
> > More fool you for using either of them. But at least the 2nd is
> > flagging to the tired eye that something pretty damn dangerous is going
> > on.
>
>
> Again the argument of "unnecessary" or "inappropriate" casts. This is
> ludicrous! Only very poor programmers mis-use casts. Since when do we
> accommodate the very poor programmers?

Well, if either version of the above is a true example of your code, I
think it's quite likely that you're misusing casts. Not because such
code is inherently wrong, but because the contexts in which such code
would be correct are overwhelmingly less common than contexts where
less-than-expert programmers mistakenly think that they are correct.

ThosRTanner

unread,
Jul 18, 2006, 8:55:54 AM7/18/06
to

Pete Becker wrote:
> Steve Clamage wrote:
> > Pete Becker wrote:
> >
> >> ThosRTanner wrote:
> >>
> >>>
> >>> In general however, a language that is designed to make it difficult to
> >>> make mistakes and make it easy to spot where mistakes are likely is
> >>> infinitely preferable over the other.
> >>
> >>
> >>
> >> Hence the stunning success of Pascal. <g>
> >
> >
> > I'm sure Pete would agree that the strong typeing of Pascal was not the
> > primary reason for Pascal failing to become a popular and successful
> > development language.
> >
>
> Nevertheless, it is a counterexample to the original assertion. Pascal
> code is best written by a team of two programmers: one to write the code
> and one to write the semicolons.
I did say in general

> Seriously: Pascal is annoying in its attempts to enforce orthodoxy, and
> that's separate from the specific problems that Steve mentions. I used
> Turbo Pascal for several years. Moving from Pascal to C was a tremendous
> relief.

C++ with Gimpel lint (with strong type checking) is a much better
language to program in than C++ ...

Mind you C++ with an IDE is also a much better language than C++ with
an editor.

I wouldn't know about Pascal though. My path was Fortran -> Assembler
-> BCPL -> C -> C++ -> Java (OK, I'm learning Java, and some of the C++
I've learnt has helped, some has hindered).

Francis Glassborow

unread,
Jul 18, 2006, 8:02:04 AM7/18/06
to
In article <QCSug.11572$j7.3...@news.indigo.ie>, Frederick Gotham
<fgot...@SPAM.com> writes

>Here's my own calculations:
>---------------------------
>
>(1) 26 letters in the English part of the alphabet (i.e. without diacritics).
>
>(2) Each has an uppercase/lowercase form, so that's 52 distinct characters.
>
>Pretend you're dealing with a number system whose radix is 52, and you want
>to calculate the greatest value representable in two digits. Then add one.
>
>51(52^1) + 51(52^0) + 1
>
>= 2652 + 51 + 1
>
>= 2704
>
You forgot underscore, and you forgot that the ten digits are legal as
the second character.

--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

---

Krzysztof Zelechowski

unread,
Jul 18, 2006, 9:18:37 AM7/18/06
to

Uzytkownik "kanze" <ka...@gabi-soft.fr> napisal w wiadomosci
news:1153126683.2...@35g2000cwc.googlegroups.com...

> "Krzysztof Zelechowski" wrote:
>> assert(Target(x) == x);
>
> You may get an implementation defined signal before the assert
> trips (which probably doesn't matter). You may also fail to
> trip even when you should, if the conversion is between signed
> and unsigned types, e.g. Target is unsigned int, Source is int,
> and the value of x is -3.
>

My code should be used when the compiler issues a warning. Should there be
a warning about an implicit cast from int to unsigned int, my code would
fail. But the OP wanted to handle a warning about truncation.

Chris

kanze

unread,
Jul 18, 2006, 10:45:55 AM7/18/06
to
"Krzysztof Zelechowski" wrote:
> Uzytkownik "kanze" <ka...@gabi-soft.fr> napisal w wiadomosci
> news:1153126683.2...@35g2000cwc.googlegroups.com...
> > "Krzysztof Zelechowski" wrote:
> >> assert(Target(x) == x);

> > You may get an implementation defined signal before the
> > assert trips (which probably doesn't matter). You may also
> > fail to trip even when you should, if the conversion is
> > between signed and unsigned types, e.g. Target is unsigned
> > int, Source is int, and the value of x is -3.

> My code should be used when the compiler issues a warning.
> Should there be a warning about an implicit cast from int to
> unsigned int, my code would fail. But the OP wanted to handle
> a warning about truncation.

Actually, the original poster was complaining about C++ code
being too readable, but this sub-thread has drifted considerably
away from that topic. Seungbeom Kim asked for a range checked
conversion, with an assertion failure if the source value didn't
fit into the target type. I was just pointing out that in some
special cases, your assert would pass despite an error. And
that formally, at least, the expression Target(x), in itself,
may trigger an implementation defined signal (although in this
case, that probably doesn't matter).

--
James Kanze GABI Software
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

Frederick Gotham

unread,
Jul 18, 2006, 11:01:24 AM7/18/06
to
kanze posted:


> Actually, the original poster was complaining about C++ code
> being too readable


No, I was complaining about words taking too much horizontal screenspace.


Readability is great, but not at the expense of taking up half the screen.


--

Frederick Gotham

mark

unread,
Jul 18, 2006, 12:02:11 PM7/18/06
to

Francis Glassborow wrote:
> In article <b8knb2lfciothjm4g...@4ax.com>, Gennaro Prota
> <gennar...@yahoo.com> writes
> >On Tue, 11 Jul 2006 10:32:28 CST, "kanze" <ka...@gabi-soft.fr> wrote:
> >
> >>There are 32949 legal two character names.
> >
> >Care to explain the origin of that number?
>
> Yes definitely an odd number for that claim 523 * 7 * 3 * 3 does not
> seem to offer much promise in this context.

It does if you notice that 7*3*3 is 63...

> I think there are 3339 (53 *
> 63) legal 2 character names in C++ + 53 single character ones.

Apparently James accidently typed 523*63 into his calculater, rather
than 53*63.

Mark Williams

kanze

unread,
Jul 18, 2006, 12:01:13 PM7/18/06
to
Gennaro Prota wrote:
> On Tue, 11 Jul 2006 10:32:28 CST, "kanze" <ka...@gabi-soft.fr> wrote:

> >There are 32949 legal two character names.

> Care to explain the origin of that number?

Keyboard bounce when I was entering the numbers on the
calculator? Or maybe I simply forgot to clear the input before
entering the first number. If nothing else, there's definitly a
digit too many. What I though I was calculating was 53 (26
upper, 26 lower and _) times 64 (the above, plus 10 digits, or
nothing). Which gives 3392, unless I've made some other mistake
this time.

Oh, well. I've never claimed to be perfect, or to never make
mistakes.

--
James Kanze GABI Software
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

SuperKoko

unread,
Jul 18, 2006, 12:12:33 PM7/18/06
to

Frederick Gotham wrote:
> SuperKoko posted:
>
> > The const_cast is very inappropriate here.
>
>
> It's there for a reason.
>
> I don't use unnecessary casts.
>
> I don't use inappropriate casts.
>
>
For such very simple functions, usually, programmers write the function
twice:
template <class T>

inline void AdvPtr(T*& p, std::size_t const bytes) {
p = reinterpret_cast<T*>(
reinterpret_cast<const char *>(p) + bytes);
}
template <class T>
inline void AdvPtr(const T*& p, std::size_t const bytes) {
p = reinterpret_cast<const T*>(

reinterpret_cast<char *>(p) + bytes);
}

> > Worst, actually, reinterpret_casting from a misaligned char*
>
>
> No such thing as a misaligned char*.
>
>

No, but there exists something such as a char* which is not enough
aligned to be safely/portably converted to a T* where T is a type which
might require alignment.
I mean that on a 68000 CPU, doing

int x[2];
int* p=x;
AdvPtr(p,sizeof(int)-1); /* VERY BAD idea */
AdvPtr(p,1); /* Don't expect it to points to x[1] : The first
conversion might have "dropped" the lower bits of the pointer */

So, I can't see any *portable* usage of this function with values of
bytes not equal to a multiple of sizeof(T).
That's why, you don't need a cast at all:
template <class T>


inline void AdvPtr(T*& p, std::size_t const bytes) {

p = bytes/sizeof(T); /* portable, though probably not useful */
}

> unsigned char* would indeed be preferable if you actually access the data at
> the specified address.
>
> If you're just doing pointer arithmetic though, there's no need for the
> superfluous "unsigned".
>

I didn't said that your code needed an unsigned char... I said that,
when working on raw data, unsigned char* are good candidates for
generic pointers... (e.g. int* are very bad candidates).


>
> > T* p=static_cast<T*>(static_cast<void*>(my_char_pointer+offset));
>
>
> Ridiculous overkill. (Not to mention it doesn't take care of constness.)
>

It *takes care* of constness... This code is supposed to be put in a
particular context... Not as a generic dangerous, error prone function.

Back to your question:


> And again we have melodramatic use of "dangerous". There's nothing wrong
> with the way I use casts.

The mere interface of your function is *dangerous*!
If the caller pass a non-correctly aligned "bytes" argument, it will
have non-portable, implementation-specific results.

Again, where do you use this function?
Do you use it like that?

AdvPtr(p, sizeof(T)*index);

In that case, p+=index; is better...
I can't see any high-level useful application of your function.

Mhhh... If <cstdarg> didn't existed, I guess that your AdvPtr function
could be useful to implement this variable-argument mechanism, though
it would *not be portable*.

ThosRTanner

unread,
Jul 18, 2006, 12:14:06 PM7/18/06
to

Frederick Gotham wrote:
> ThosRTanner posted:
>
> > Is this a troll?
>
>
> Great way to start a conversation -- congratulations on the social skills.
Why, thank you. You are too kind.

>
> > Although I'd agree that there are a lot of cowboy programmers out there
> > who have apalling design and coding practices, in the same way that
> > there are cowboy builders, plumbers, ..., I think you will find that
> > expert C++ programmers get that way from learning the language, they
> > aren't born knowing the ins and outs of C++ programmers.
>
>
> The same can be said for any pursuit.
>
> A boxer shouldn't expect to win a title within his first month of training.
>
> A plumber shouldn't expect to be the best plumber in the city after his
> first month of training.
>
> A surgeon shouldn't expect to be top surgeon in his practice within his
> first month.
>
> A programmer shouldn't expect to be the best programmer in the world after
> his first month.
>
> Practise makes perfect -- programming is no exception.
>

Then why do you want a language that is only suitable for those who are
expert in that language? It is ultimately self defeating.

> > In general however, a language that is designed to make it difficult to
> > make mistakes and make it easy to spot where mistakes are likely is
> > infinitely preferable over the other. This is why high level languages
> > are preferable to assembly code - which in turn is prefereable to
> > programming the machine in hex codes.
>
>
> Yes, but how dumb do you want to go? C++ dumb, or Java dumb?

I don't know. I'd rather get the design right, and find it easy to
convert the design to the implementation. A language that doesn't have
so many pitfalls for the unwary is, in those terms, a better language.
A language where the compiler can't tell the difference between a
function call and a declaration has problems.


>
> > There are areas where C++ is NOT friendly to the novice, and causes
> > grief and pain - this is why coding standards evolve.
>
>
> Just because something is difficult at the start doesn't mean you should
> give up.

I wasn't suggesting people give up. I was merely pointing out that
there are places where C++ makes life un-necessarily difficult. Great
for book writers and pundits, but not so good for the rest of us.

> Learning to walk is hard. Learning to talk is hard. Learning to throw a
> ball is hard. Learning to read is hard. Learning to write is hard. Learning
> to perform a heart transplant is hard.

Walking, talking, throwing, reading, writing are tools. Peforming heart
transplants is not a tool.

Tools are meant to make things easier. In the long run, what sort of
tool is going to be more succesful, more frequently used. A tool that
only experts can use without causing damage, or a tool that many people
can use to do what they need.


>
>
> >> And who's to say if a cast is "inappropriate"... ?
> >
> > Or indeed necessary
>
>
> You either get a compile error or you don't.
>
>
> >> C was built on a foundation of programmers who are competent, not on
> >> holding the hands of beginners who aren't out of diapers yet. C++
> >> should build on this proud mentality.
> >
> > I have no doubt it is a proud mentality. Whether it is a mentality that
> > makes things better for others is rather open to question.
>
>
> I was able to learn C++. You were able to learn C++.
>
> I may have above average intelligence, but I'm no genius -- yet still I can
> program proficiently.

I realise the analogy can be carried to far, but do you just program
someone elses designs, or do you design and program? As far as I can
tell, getting the design right is the important bit. Coding to some
extent is like building from an architects plans. And I'd rather the
tools I used for coding my designs didn't involve me spending a lot of
time avoiding subtleties and vagaries.

>
> >> My efficient, fully-portable, Standard-compliant code contains many
> >> casts. Some are necessary to make the code compile. Some are necessary
> >> to suppress compiler warnings. But they're all there for a reason!
> > And all are somewhat dangerous.
>
>
> No more dangerous than eating fish. Watch for bones and you'll have no
> problem.

Or buy filleted fish.

> Of course, if you don't watch for bones, then it's your own problem.
>
>
> >> Why should expert programmers be burdened with unwieldy names? It
> >> insults human intelligence.
> > I'd find it pretty difficult to insult that level of intelligence.
>
>
> There are people in my college who employ use of a calculator to add two
> single-digit numbers.

And?

> >> Some may hold in derision my use of old-style casts, but I'll
> >> definitely prefer:
> >>
> >> int *pi = (int*)pc;
> >>
> >> over:
> >>
> >> int *pi = reinterpret_cast<int*>(const_cast<char*>(pc));
> >>
> > More fool you for using either of them. But at least the 2nd is
> > flagging to the tired eye that something pretty damn dangerous is going
> > on.
>
>
> Again the argument of "unnecessary" or "inappropriate" casts. This is
> ludicrous! Only very poor programmers mis-use casts. Since when do we
> accommodate the very poor programmers?

Any programmer who uses a cast without a large amount of documentation
surrounding it is more than poor.

> And again we have melodramatic use of "dangerous". There's nothing wrong
> with the way I use casts. Here's some code of mine which makes brilliant
> use of the feature known as casts. The code's objective is to increment a
> pointer by a specified number of bytes. Please let me know where you feel
> the danger lies:
>
> #include <cstddef>
>
> template<class T>
> inline void AdvPtr( T *&p, std::size_t const bytes )
> {
> p = reinterpret_cast<T*>(
> const_cast<char*>(
> reinterpret_cast<char const*>(p) + bytes
> )
> );
> }

Well, for a start, if p is a pointer to a T, why are you incrementing
by a number of bytes that is not a multiple of sizeof(T). In which
case, why not just use p += num_elems;

So what have we got:
1) Removing constness from a pointer is always dangerous. In this
situation it is safe, but only because you have a completely
unnecessary cast to a const pointer.
2) If bytes is not a multiple of sizeof(T), you are liable to end up
pointing into the middle of some data structure in an embarassing
fashion
3) If bytes is not a multiple of the alignment of T, you will turn p
into a non-aligned pointer, This will either crash or slow your system
down something chronic.

So basically, I'd be hard put to it to find what is right with this.

Cheers

Tom

Richard Smith

unread,
Jul 18, 2006, 12:18:04 PM7/18/06
to

Frederick Gotham wrote:
> Here's some code of mine which makes brilliant
> use of the feature known as casts. The code's objective is to increment a
> pointer by a specified number of bytes. Please let me know where you feel
> the danger lies:
>
> #include <cstddef>
>
> template<class T>
> inline void AdvPtr( T *&p, std::size_t const bytes )
> {
> p = reinterpret_cast<T*>(
> const_cast<char*>(
> reinterpret_cast<char const*>(p) + bytes
> )
> );
> }

Please, please, please tell me this is a wind up. Surely it's obvious
why this is dangerous? For a start, what if bytes is not a multiple of
the size (and/or alignment depending on the function's intended use) of
T? Either you started off with an inappropriately alligned pointer, or
you'll end up with one. An improvement would be to include an
assertion to that effect.

Second, the name itself it highly misleading. I'm sure most
programmers would infer from the function name that it simply did p +=
bytes -- i.e. that the second argument was a number of T objects to
iterate over. If you must have a function that does this, give it a
better name -- bytewise_advance perhaps? And giving a function as
dangerous as this a lengthy name is a positive thing -- I would hope
that any calls to such a function would be few and far between and
quickly abstracted in a safer interface.

Thirdly, what's with the const_cast? As far as I can see this is pure
obfuscation. If you don't add constness with the inner
reinterpret_cast, you don't need to remove it again. The presence of
this cast itself dangerous by virtue of misleading programmers into
thinking that this function somehow subverts the constness of the
object; it does not. And anything that unnecessarily misleads other
programmers is, to my mind, dangerous.

But I can't believe that this could possibly have been a serious
question: surely anyone who wrote code like that would find themselves
out of work faster than they could say "reinterpret_cast"?

--
Richard Smith

Frederick Gotham

unread,
Jul 18, 2006, 11:20:05 AM7/18/06
to
Kuyper posted:

>> You either get a compile error or you don't.
>
> Yes, but that's hardly a useful criterion.
>
> In some cases, the reason why a cast is inappropriate only shows up at
> run time. In some cases, it only shows up when you port the code to a
> platform with unexpected (but legal) properties.


Again we're making allowances for stupid, non-portable code. It's the
programmer's responsibility to know how flexibly C++ can be implemented.
When reading posts on comp.lang.c++, etc., I stop reading as soon as I see
something like:

struct Arb {

int *p;
double i;
};

int main()
{
Arb obj;

memset(obj,0,sizeof obj);
}


This code is stupid and non-portable, plain and simple.

I'm against putting stabilisers on the wheels of C++ to accommodate brain-
amputee programmers.


> In some cases, the problem comes up only when someone who's not as
> familiar with the code as an idealist would like them to be makes a
> change to something.


I can't think of any such situation. (Unless you're talking about something
as dumb as:

int *p = reinterpret_cast<int*>(0,0);


>> I was able to learn C++. You were able to learn C++.
>
> From your comments, I suspect that you still have a lot to learn, of
> the kinds of things that aren't covered by ordinary textbooks.


Funny, I would consider my core knowledge of C++ to be quite extensive.


>> No more dangerous than eating fish. Watch for bones and you'll have no
>> problem.
>>
>> Of course, if you don't watch for bones, then it's your own problem.
>
> That analogy underestimates both the danger, and the difficulty of
> avoiding it.


I find it *extremely* easy to use casts properly.

I never make an unnecessary or inappropriate cast.

Although a code sample of mine may contain several instances of const_cast,
static_cast, reinterpret_cast, and even C-style casts, it's all fully-
portable and is absent of undefined behaviour.

Do they change the 100-metre sprint because babies fall over when they try
to stand up?


>> >> Some may hold in derision my use of old-style casts, but I'll
>> >> definitely prefer:
>> >>
>> >> int *pi = (int*)pc;
>> >>
>> >> over:
>> >>
>> >> int *pi = reinterpret_cast<int*>(const_cast<char*>(pc));
>> >>
>> > More fool you for using either of them. But at least the 2nd is
>> > flagging to the tired eye that something pretty damn dangerous is
>> > going on.
>>
>>
>> Again the argument of "unnecessary" or "inappropriate" casts. This is
>> ludicrous! Only very poor programmers mis-use casts. Since when do we
>> accommodate the very poor programmers?
>
> Well, if either version of the above is a true example of your code, I
> think it's quite likely that you're misusing casts.


Context is everything. Assertions made out of context are nothing.


> Not because such code is inherently wrong, but because the contexts in
> which such code would be correct are overwhelmingly less common than
> contexts where less-than-expert programmers mistakenly think that they
> are correct.


Indeed. But I'm not a less-than-expert programmer, and I'm not about to
dumb-down my own method of programming just so my code looks less
suspicious.


--

Frederick Gotham

kanze

unread,
Jul 18, 2006, 12:27:01 PM7/18/06
to
Frederick Gotham wrote:

> I don't use unnecessary casts.

> I don't use inappropriate casts.

Then we should assume that message
<0iMsg.11333$j7.3...@news.indigo.ie> in
comp.lang.c++.moderated was a forgery. The message claims to be
from you, and contains the following code:

#define SomeKindOfCompileTimeAssert(expr) typedef char
Compass[(expr)?4:-4]

unsigned Amalg(unsigned char const * const p)
{
/* Firstly, ensure no padding: */
SomeKindOfCompileTimeAssert(
CHAR_BIT * sizeof(unsigned)
== std::numeric_limits<unsigned>::digits
);
return reinterpret_cast<unsigned const&>(*p);
}

It's hard to imagine a more inappropriate cast---as I pointed
out in my response there, it core dumps on my machine (and on
most non-Intel platforms), probably gives the wrong answer on an
Intel (and certainly gives the wrong answer on some other
machines) AND there is a very good perfectly portable perfectly
correct solution which doesn't use casts.

When you post code like this, or like your AdvPtr in the
previous posting, it makes it very hard to take any of your
claims seriously.

--
James Kanze GABI Software
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

kanze

unread,
Jul 18, 2006, 12:23:52 PM7/18/06
to
Frederick Gotham wrote:
> ThosRTanner posted:

> > Is this a troll?

> Great way to start a conversation -- congratulations on the
> social skills.

Aren't you the one who started it? With insinuations along the
lines of "not-so-apt" and "expert programmer" (with the
suggestion that people who need to write clear and readable code
aren't expert).

Whether you like it or not, you're arguing against proven
software engineering practice.

> > Although I'd agree that there are a lot of cowboy
> > programmers out there who have apalling design and coding
> > practices, in the same way that there are cowboy builders,
> > plumbers, ..., I think you will find that expert C++
> > programmers get that way from learning the language, they
> > aren't born knowing the ins and outs of C++ programmers.

> Practise makes perfect -- programming is no exception.

Actually, practice doesn't make perfect, at least where
programming (and most other human exploits) are concerned. No
matter how much you practice, you'll never be perfect.

> > In general however, a language that is designed to make it
> > difficult to make mistakes and make it easy to spot where
> > mistakes are likely is infinitely preferable over the other.
> > This is why high level languages are preferable to assembly
> > code - which in turn is prefereable to programming the
> > machine in hex codes.

> Yes, but how dumb do you want to go? C++ dumb, or Java dumb?

What's dumb about writing readable code? Java or C++?
(Actually, I don't quite get the comparison. It's a lot harder
to write robust, readable code in Java than in C++. Partially,
at least, because Java code is so full of casts, and they don't
stand out.)

> > There are areas where C++ is NOT friendly to the novice, and
> > causes grief and pain - this is why coding standards evolve.

> Just because something is difficult at the start doesn't mean
> you should give up.

Aren't there enough difficult things to learn without
artificially adding to the list? I'm paid to produce working
solutions, not to master all sorts of unnecessary trickery just
to prove that I can to something a lot of other people can't.

> >> And who's to say if a cast is "inappropriate"... ?

> > Or indeed necessary

> You either get a compile error or you don't.

??? If you use a cast, you'll almost never get a compiler
error. Even when it's unnecessary. And a lot of use of casts
won't give you a compiler error if you forget it; you'll just
get wrong results.

> >> C was built on a foundation of programmers who are
> >> competent, not on holding the hands of beginners who aren't
> >> out of diapers yet. C++ should build on this proud
> >> mentality.

> > I have no doubt it is a proud mentality. Whether it is a
> > mentality that makes things better for others is rather open
> > to question.

> I was able to learn C++. You were able to learn C++.

> I may have above average intelligence, but I'm no genius --
> yet still I can program proficiently.

For what definition of proficiently? In my mind, programming
proficiently means writing code which others can easily read and
maintain. Sometimes, a cast is necessary, but I've yet to see
any case where a type conversion (implicit or explicit) made
code more readable and easier to maintain.

> >> Some may hold in derision my use of old-style casts, but I'll
> >> definitely prefer:

> >> int *pi = (int*)pc;

> >> over:

> >> int *pi = reinterpret_cast<int*>(const_cast<char*>(pc));

> > More fool you for using either of them. But at least the 2nd
> > is flagging to the tired eye that something pretty damn
> > dangerous is going on.

> Again the argument of "unnecessary" or "inappropriate" casts.
> This is ludicrous! Only very poor programmers mis-use casts.

You posted an example of code in comp.lang.c++.moderated which
mis-used casts. Does this mean that you're a poor programmer?
Or only that there were contraints that, for one reason or
another, you hadn't taken into consideration?

In real life code, casts are rarely necessary, and usually only
at the lowest levels. Their presence is a sign that something
dangerous is going on. I want them visible.

> Since when do we accommodate the very poor programmers?

More insinuations. It would help if you'd present some facts.
I find code with the new style casts much easier to read and
maintain (and code without any casts even easier). Are you
saying that I'm a "very poor programmer"?

> And again we have melodramatic use of "dangerous".

Nothing melodramatic. Just a basic reality.

> There's nothing wrong with the way I use casts.

Except in your public postings in comp.lang.c++.moderated.

> Here's some code of mine which makes brilliant use of the
> feature known as casts. The code's objective is to increment
> a pointer by a specified number of bytes. Please let me know
> where you feel the danger lies:

> #include <cstddef>

> template<class T>
> inline void AdvPtr( T *&p, std::size_t const bytes )
> {
> p = reinterpret_cast<T*>(
> const_cast<char*>(
> reinterpret_cast<char const*>(p) + bytes
> )
> );
> }

Could you please tell me what the purpose of this function is?
About the only use I can find for it is to generate core dumps.

If you have code like this in anything other than the lowest
level of programming (say, in an operating system kernel, or a
garbage collector), then I think you have a problem. The first
thing I'd do about it is throw out all of the code which calls
this function, and then throw out the function.

--
James Kanze GABI Software
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

Frederick Gotham

unread,
Jul 18, 2006, 12:32:44 PM7/18/06
to
ThosRTanner posted:

>> Learning to walk is hard. Learning to talk is hard. Learning to throw a
>> ball is hard. Learning to read is hard. Learning to write is hard.
>> Learning to perform a heart transplant is hard.
>
> Walking, talking, throwing, reading, writing are tools. Peforming heart
> transplants is not a tool.
>
> Tools are meant to make things easier. In the long run, what sort of
> tool is going to be more succesful, more frequently used. A tool that
> only experts can use without causing damage, or a tool that many people
> can use to do what they need.


Wordplay.


>> No more dangerous than eating fish. Watch for bones and you'll have no
>> problem.
> Or buy filleted fish.


Filleted fish is more expensive in terms of money.

Dumbed-down programming languages are more expensive in terms of
efficiency.


>> There are people in my college who employ use of a calculator to add
>> two single-digit numbers.
> And?


Context: An example of a insult to human intelligence.


> Any programmer who uses a cast without a large amount of documentation
> surrounding it is more than poor.


Depends if she intends her code to be read by poor programmers.


> Well, for a start, if p is a pointer to a T, why are you incrementing
> by a number of bytes that is not a multiple of sizeof(T). In which
> case, why not just use p += num_elems;
>
> So what have we got:
> 1) Removing constness from a pointer is always dangerous. In this
> situation it is safe, but only because you have a completely
> unnecessary cast to a const pointer.
> 2) If bytes is not a multiple of sizeof(T), you are liable to end up
> pointing into the middle of some data structure in an embarassing
> fashion
> 3) If bytes is not a multiple of the alignment of T, you will turn p
> into a non-aligned pointer, This will either crash or slow your system
> down something chronic.


The topic of this thread is not the objective of my function, but rather
the successful use of casts.

--

Frederick Gotham

Bo Persson

unread,
Jul 18, 2006, 12:38:23 PM7/18/06
to

"Frederick Gotham" <fgot...@SPAM.com> skrev i meddelandet
news:iR5vg.11603$j7.3...@news.indigo.ie...

> kanze posted:
>
>
>> Actually, the original poster was complaining about C++ code
>> being too readable
>
>
> No, I was complaining about words taking too much horizontal
> screenspace.

The language design could make an attempt to choose short word, where
available. The original Ada designers did that, choosing task over
process, and limited over protected. But absolutely no proc, or prot,
or fmod.

In C++ we have an advantage over C that we overload functions, to
avoid things like fmod. That's good, and should be used.

Otherwise we could end up in the C marshes, and try to figure out why
one of fclose, fread, fmod, ftell, and fwrite doesn't take a FILE*
parameter. Not very obvious at all.

>
>
> Readability is great, but not at the expense of taking up half the
> screen.

Then you are lucky that this week there is a 20% discount on 24 inch
wide screen monitors.

http://accessories.us.dell.com/sna/productlisting.aspx?c=us&category_id=6198&cs=04&l=en&mnf=694

That's another option.


Bo Persson

Frederick Gotham

unread,
Jul 18, 2006, 12:52:39 PM7/18/06
to
SuperKoko posted:

> For such very simple functions, usually, programmers write the function
> twice:
> template <class T>
> inline void AdvPtr(T*& p, std::size_t const bytes) {
> p = reinterpret_cast<T*>(
> reinterpret_cast<const char *>(p) + bytes);
> }
> template <class T>
> inline void AdvPtr(const T*& p, std::size_t const bytes) {
> p = reinterpret_cast<const T*>(
> reinterpret_cast<char *>(p) + bytes);
> }


I don't duplicate code.

I had actually started off with two functions, and strove to merge them --
and I was successful.


>> > Worst, actually, reinterpret_casting from a misaligned char*
>>
>>
>> No such thing as a misaligned char*.
>>
>>
> No, but there exists something such as a char* which is not enough
> aligned to be safely/portably converted to a T* where T is a type which
> might require alignment.


Correct.

The objective of the function is to increment a pointer by a specified
number of bytes -- it's the client's problem if they end up with a pointer
to a misaligned object.

One plausible use of it would be, (assuming we have an "alignof" operator):

AdvPtr(p, alignof(*p));


> So, I can't see any *portable* usage of this function with values of
> bytes not equal to a multiple of sizeof(T).


How about multiples of alignof(T)? It's common that an object's alignment
requirements are less than its size.

Anyway, the objective of my function isn't the topic here -- the topic is
the use of casts.

If you wish to discuss the function's objective, here's a relevant thread:

http://groups.google.ie/group/comp.lang.c++/browse_frm/thread/5ffe109aa07bf
d16/85e926012c055278?lnk=st&q=insubject%3Aalignof+author%
3AFrederick+author%3AGotham&rnum=1&hl=en#85e926012c055278


> Back to your question:
>> And again we have melodramatic use of "dangerous". There's nothing
>> wrong with the way I use casts.
>
> The mere interface of your function is *dangerous*!
> If the caller pass a non-correctly aligned "bytes" argument, it will
> have non-portable, implementation-specific results.


Which is why the caller shouldn't pass an incorrect value for "bytes".

Is array indexing dangerous? Nothing's to stop me writing:

int array[8];

array[242] = 4;


Quick! Let's ban array indexing!

It's *D* *A* *N* *G* *E* *R* *O* *U* *S*!


It's possible to decrement a pointer to before the first element of an
array.

Quick! Let's ban pointer decrementation!

It's *D* *A* *N* *G* *E* *R* *O* *U* *S*!


Signed integer arithmetic produces undefined behaviour upon overflow.

Quick! Let's ban signed integer arithmetic!

It's *D* *A* *N* *G* *E* *R* *O* *U* *S*!


Writing programs in C++ can result in undefined behaviour.

Quick! Let's move to Java!

C++ is *D* *A* *N* *G* *E* *R* *O* *U* *S*!


> Again, where do you use this function?
> Do you use it like that?
>
> AdvPtr(p, sizeof(T)*index);
>
> In that case, p+=index; is better...
> I can't see any high-level useful application of your function.


Again, that is not the topic here.


--

Frederick Gotham

kuy...@wizard.net

unread,
Jul 18, 2006, 6:05:42 PM7/18/06
to
Frederick Gotham wrote:
> Kuyper posted:

.
> I'm against putting stabilisers on the wheels of C++ to accommodate brain-
> amputee programmers.

I agree; but you're exaggerating the situation when you imply that the
feature we're talking about imposes costs as serious as putting
unnecessary stabilizers on wheels, and you're exaggerating grotesquely
when you imply that the only people who would benefit from this featue
are brain-amputees. The long names of the new conversion operators
impose a very minor cost. They help reduce (not elliminate) the making
of mistakes of a kind that, from my personal experience, are made by
programmers of all experience levels, though substantially less often
by experts than by novices.

> > In some cases, the problem comes up only when someone who's not as
> > familiar with the code as an idealist would like them to be makes a
> > change to something.
>
>
> I can't think of any such situation. (Unless you're talking about something
> as dumb as:
>
> int *p = reinterpret_cast<int*>(0,0);

The conditions determining whether a type conversion does what it's
intended to do safely and efficiently are often complex. Whether or not
those conditions are met can often depend at run time upon code that is
very distant from the site of the conversion. Ideally, a person can
verify that a given conversion is appropriate by looking either at
actual code that is near to the site of the conversion, or at
documention. In reality, programmers of only moderate levels of
competence don't always know what those requirements are. Real code is
often poorly documented. Even well-designed code may have been designed
around other constraints that force you to look far away from the site
of a conversion, to confirm the validity of that conversion, and in the
real world code design is often significantly less than perfect. In
reality, code changes must be made by the person who is available,
rather than the person that you would like to have available, and the
person who is available make not be sufficiently familiar with the
program to know how to find out everything he needs to know to confirm
the validity of a conversion.

For all of these reasos, any language feature that makes it easier to
notice and evaluate the validity of a conversion provides a distinct
advantage.

> >> I was able to learn C++. You were able to learn C++.
> >
> > From your comments, I suspect that you still have a lot to learn, of
> > the kinds of things that aren't covered by ordinary textbooks.
>
>
> Funny, I would consider my core knowledge of C++ to be quite extensive.

Core knowledge is something that's covered by ordinary textbooks.
Writing maintainable code is something that's often neglected in those
books. Most people either never learn to write maintainable code, or
start learning only after they've burned badly enough to appreciate how
important maintainability is. I think you haven't reached that point in
your career yet.

> I find it *extremely* easy to use casts properly.
>
> I never make an unnecessary or inappropriate cast.

The const_cast in your code sample served no useful purpose, and the
reinterpret_cast is needed only if your function takes arguments that
can cause undefined behavior either when the function is called, or
when it returns.

> Although a code sample of mine may contain several instances of const_cast,
> static_cast, reinterpret_cast, and even C-style casts, it's all fully-
> portable and is absent of undefined behaviour.

> Do they change the 100-metre sprint because babies fall over when they try
> to stand up?

The 100-meter sprint is designed to seperate the very best runners from
runners who are almost the very best. A programming language designed
only for the very best programmers is a programming language that will
die a quick and well-deserved death, because the very best of anything
is, by definition, rare. There aren't enough of the very best
programmers to fill all of the programming positions that need to be
filled.

.
> > Not because such code is inherently wrong, but because the contexts in
> > which such code would be correct are overwhelmingly less common than
> > contexts where less-than-expert programmers mistakenly think that they
> > are correct.
>
>
> Indeed. But I'm not a less-than-expert programmer, and I'm not about to
> dumb-down my own method of programming just so my code looks less
> suspicious.

In the unlikely event that you're as good as you say you are, you've
ensured that your code is unmaintainable by less competent programmers.
I wouldn't hire someone who wrote code like that (unless I absolutely
had to - which in itself is an example of the very same problem that
I'm describing).

Frederick Gotham

unread,
Jul 18, 2006, 6:57:59 PM7/18/06
to
Kuyper posted:


> The const_cast in your code sample served no useful purpose, and the
> reinterpret_cast is needed only if your function takes arguments that
> can cause undefined behavior either when the function is called, or
> when it returns.


Did you analyse the code to see why the const_cast is indeed necessary? The
function should be able to work with:

(1) Pointer to non-const.
(2) Pointer to const.


As follows:

int *p1;

int const *p2;

AdvPtr(p1, sizeof *p1);

AdvPtr(p2, sizeof *p2);


If I were to remove the const_cast, then it would only work with "pointer
to const". Here's is the original code which works with both kinds of
pointer:


#include <cstddef>

template<class T>
inline void AdvPtr( T *&p, std::size_t const bytes )
{

p = reinterpret_cast<T*>(

const_cast<char*>(
reinterpret_cast<char const*>(p) + bytes
)
);
}


Here is the form with "const_cast" removed; it only works with "pointer to
const":


#include <cstddef>

template<class T>
inline void AdvPtr( T *&p, std::size_t const bytes )
{

p = reinterpret_cast<T*>(

reinterpret_cast<char const*>(p) + bytes

);
}


While we're playing the "Let's restrict perfectly-good-code game", here's
one that will only work for "pointer to non-const":


#include <cstddef>

template<class T>
inline void AdvPtr( T *&p, std::size_t const bytes )
{

p = reinterpret_cast<T*>(

reinterpret_cast<char*>(p) + bytes
);
}

--

Frederick Gotham

Keith Thompson

unread,
Jul 19, 2006, 2:03:45 AM7/19/06
to
fgot...@SPAM.com (Frederick Gotham) writes:
[...]

> I find it *extremely* easy to use casts properly.
>
> I never make an unnecessary or inappropriate cast.

You've done so in this very thread:

| unsigned long long const gdp = 12485725486486764U;
[...]
| unsigned long long const population = 297279178249U;
[...]
| unsigned gdp_per_capita = (unsigned)(gdp / population);

The cast is unnecessary. Without the cast, the expression is
implicitly converted to unsigned anyway. (Whether the cast is
inappropriate is another question; in my opinion it is.)

Be careful about the word "never".

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.

Krzysztof Zelechowski

unread,
Jul 19, 2006, 10:56:29 AM7/19/06
to

Uzytkownik "kanze" <ka...@gabi-soft.fr> napisal w wiadomosci
news:1153229444.0...@s13g2000cwa.googlegroups.com...

> Frederick Gotham wrote:
>> ThosRTanner posted:
>
>> >> And who's to say if a cast is "inappropriate"... ?
>
>> > Or indeed necessary
>
>> You either get a compile error or you don't.
>
> ??? If you use a cast, you'll almost never get a compiler
> error. Even when it's unnecessary. And a lot of use of casts
> won't give you a compiler error if you forget it; you'll just
> get wrong results.
>

Mr Gotham probably meant that a cast is necessary when you get a
compile-time error when you do not use it: no error = no cast. And, since
not getting compile-time errors seems to be his main objective, there is
nothing to ???? about. You just use the cast to compile and deliver your
product and afterwards, when it breaks at run time, you happily explain that
it was only a demo ;-)

Chris

ThosRTanner

unread,
Jul 19, 2006, 11:56:35 AM7/19/06
to

Frederick Gotham wrote:
> ThosRTanner posted:
>
> >> Learning to walk is hard. Learning to talk is hard. Learning to throw a
> >> ball is hard. Learning to read is hard. Learning to write is hard.
> >> Learning to perform a heart transplant is hard.
> >
> > Walking, talking, throwing, reading, writing are tools. Peforming heart
> > transplants is not a tool.
> >
> > Tools are meant to make things easier. In the long run, what sort of
> > tool is going to be more succesful, more frequently used. A tool that
> > only experts can use without causing damage, or a tool that many people
> > can use to do what they need.
>
>
> Wordplay.

A point of view that is different to yours is not wordplay.

>
> >> No more dangerous than eating fish. Watch for bones and you'll have no
> >> problem.
> > Or buy filleted fish.
>
>
> Filleted fish is more expensive in terms of money.

Depends how much money choking to death on a bone involves really.

> Dumbed-down programming languages are more expensive in terms of
> efficiency.

Not if people can produce working code more easily and non-working
code less easily.

>
> >> There are people in my college who employ use of a calculator to add
> >> two single-digit numbers.
> > And?
>
>
> Context: An example of a insult to human intelligence.

In your view perhaps. It could also be laziness, or the mathematical
equivelent of dyslexia (which does exist). Neither of those are an
insult to human intelligence (though one is rather more forgivable than
the other!).

>
> > Any programmer who uses a cast without a large amount of documentation
> > surrounding it is more than poor.
> Depends if she intends her code to be read by poor programmers.

No, depends if he/she intends her code to be maintainable. We should
he/she assume he/she is going to be the only person maintaining the
program? I dare say you haven't done any maintenance programming. It
really opens your eyes.


>
>
> > Well, for a start, if p is a pointer to a T, why are you incrementing
> > by a number of bytes that is not a multiple of sizeof(T). In which
> > case, why not just use p += num_elems;
> >
> > So what have we got:
> > 1) Removing constness from a pointer is always dangerous. In this
> > situation it is safe, but only because you have a completely
> > unnecessary cast to a const pointer.
> > 2) If bytes is not a multiple of sizeof(T), you are liable to end up
> > pointing into the middle of some data structure in an embarassing
> > fashion
> > 3) If bytes is not a multiple of the alignment of T, you will turn p
> > into a non-aligned pointer, This will either crash or slow your system
> > down something chronic.
>
>
> The topic of this thread is not the objective of my function, but rather
> the successful use of casts.

I cannot see how your program snippet succesfully uses casts. It is an
accident waiting to happen.

Seungbeom Kim

unread,
Jul 19, 2006, 11:07:36 AM7/19/06
to
kanze wrote:
>> Seungbeom Kim posted:
>>> template <class Target, class Source>
>>> inline Target numeric_cast(Source x)
>>> {
>>> assert( x is in the range of Target );
>>> return static_cast<Target>(x);
>>> }
>>> (I'm not sure how to express in C++ what I wrote inside assert( );
>
>> assert( numeric_limits<Target>::max() >= x );
>
> assert( std::numeric_limits< Target >::max() >= x
> && (! std::numeric_limits< Target >::is_signed
> || (std::numeric_limits< Target >::is_integer
> ? std::numeric_limits< Target >::min() >= x
> : -std::numeric_limits< Target >::max() >= x)) )
> ;

Thanks for your idea.

But this causes numeric_cast<signed>(1) to fail the assertion,
because 'std::numeric_limits< Target >::min() >= x' is false.
You might have meant 'std::numeric_limits< Target >::min() <= x'
but this causes numeric_cast<signed>(1000000000U) to fail the assertion
(where int is 32 bits).

--
Seungbeom Kim

James Kanze

unread,
Jul 22, 2006, 8:19:06 PM7/22/06
to
ThosRTanner wrote:

> Mind you C++ with an IDE is also a much better language than
> C++ with an editor.

And what is C++ with an IDE other than C++ with a particular
editor imposed on you? If that editor happens to be better than
the one you would otherwise use, it's an improvement. If not,
it's anything but an improvement.

--
James Kanze kanze...@neuf.fr


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

James Kanze

unread,
Jul 22, 2006, 7:18:44 PM7/22/06
to
Seungbeom Kim wrote:
> kanze wrote:
>>> Seungbeom Kim posted:
>>>> template <class Target, class Source>
>>>> inline Target numeric_cast(Source x)
>>>> {
>>>> assert( x is in the range of Target );
>>>> return static_cast<Target>(x);
>>>> }
>>>> (I'm not sure how to express in C++ what I wrote inside assert( );
>>> assert( numeric_limits<Target>::max() >= x );
>> assert( std::numeric_limits< Target >::max() >= x
>> && (! std::numeric_limits< Target >::is_signed
>> || (std::numeric_limits< Target >::is_integer
>> ? std::numeric_limits< Target >::min() >= x
>> : -std::numeric_limits< Target >::max() >= x)) )
>> ;

> Thanks for your idea.

> But this causes numeric_cast<signed>(1) to fail the assertion,
> because 'std::numeric_limits< Target >::min() >= x' is false.
> You might have meant 'std::numeric_limits< Target >::min() <= x'

Obviously:-).

> but this causes numeric_cast<signed>(1000000000U) to fail the
> assertion (where int is 32 bits).

Or even numeric_cast< signed >( 1U ).

Yuck. You're right. Worse: I'm not sure right off of a good
solution. I suspect that you'd have to do something involving
the signedness of Source as well. (If the first test passes,
and !std::numeric_limits< Source >::is_signed, no further tests
are applicable.)

Note that my expression also fails in the reverse case:
numeric_limits< unsigned >( -1 )
Again, -1 gets converted to unsigned in some of the
comparisons.

The best I can come up with rapidly is:

template< bool condition >
class Discriminator
{
} ;

// Target is_signed, ! is_integer, Source is_signed
template< typename Target, typename Source >
inline bool
isValidLower( Source value, Discriminator< true >, Discriminator<
false > )
{
return -std::numeric_limits< Target >::max() <= value ;
}

// Target is_signed, is_integer, Source is_signed
template< typename Target, typename Source >
inline bool
isValidLower( Source value, Discriminator< true >, Discriminator<
true > )
{
return std::numeric_limits< Target >::min() <= value ;
}

// Target ! is_signed, is_integer, Source is_signed
template< typename Target, typename Source >
inline bool
isValidLower( Source value, Discriminator< false >, Discriminator<
true > )
{
return 0 <= value ;
}

// Source unsigned...
template< typename Target, typename Source >
inline bool
isValid( Source value, Discriminator< false >, Discriminator< false > )
{
return std::numeric_limits< Target >::max() <= value ;
}

// Source signed
template< typename Target, typename Source >
inline bool
isValid( Source value, Discriminator< true >, Discriminator< false > )
{
// Note: this may give a false negative if Target is
// unsigned and value is negative. But in this case,
// the second condition would be sure to fail anyway,
// so the results would still be false.
return std::numeric_limits< Target >::max() <= value
&& isValidLower(
value,
Discriminator< std::numeric_limits< Target >::is_signed
> >(),
Discriminator< std::numeric_limits< Target
>::is_integer> >() ) ;
}

template< typename Target, typename Source >
Target
numeric_cast( Source x )
{
assert(
isValid< Target >( x,
Discriminator< std::numeric_limits< Source
>::is_integer >(),
Discriminator< std::numeric_limits< Target
>::is_integer >() ) ) ;
return static_cast< Target >( x ) ;
}

Untested, but there's got to be a simpler solution.

--
James Kanze kanze...@neuf.fr
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

---

kwikius

unread,
Jul 23, 2006, 3:58:23 AM7/23/06
to
James Kanze wrote:

> Untested, but there's got to be a simpler solution.

http://www.boost.org/libs/numeric/conversion/doc/index.html

#include <boost/numeric/conversion/converter.hpp>
#include <limits>
#include <iostream>

template <typename Target, typename Source>

bool in_range( Source const & s)
{
typedef boost::numeric::converter<
Target,Source
> converter;
return converter::out_of_range(s) == boost::numeric::cInRange;
}

int main()
{
bool result1 =
in_range<int>(static_cast<double>(std::numeric_limits<int>::max()));
std::cout << result1 <<'\n';
bool result2 =
in_range<int>(static_cast<double>(std::numeric_limits<int>::max())+1);
std::cout << result2 <<'\n';
}

regards
Andy Little

James Kanze

unread,
Jul 23, 2006, 9:46:41 AM7/23/06
to
kwikius wrote:
> James Kanze wrote:

>> Untested, but there's got to be a simpler solution.

> http://www.boost.org/libs/numeric/conversion/doc/index.html

When I look at the paragraph "Range Checking Logic", in the
documentation, I'm not sure that they've found a simpler
solution.

--
James Kanze kanze...@neuf.fr
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

---

kwikius

unread,
Jul 23, 2006, 2:45:14 PM7/23/06
to
James Kanze wrote:
> kwikius wrote:
> > James Kanze wrote:
>
> >> Untested, but there's got to be a simpler solution.
>
> > http://www.boost.org/libs/numeric/conversion/doc/index.html
>
> When I look at the paragraph "Range Checking Logic", in the
> documentation, I'm not sure that they've found a simpler
> solution.

Don't know quite how to put this, but their solution must be simpler,
since it actually works. Heres a quick test of your solution, tried in
VC7.1 and gcc4.0

int main()
{
int result1 =
numeric_cast<int>(static_cast<double>(std::numeric_limits<int>::max()));
std::cout << result1 <<'\n';
int result2 =
numeric_cast<int>(static_cast<double>(std::numeric_limits<int>::max())
+ 1);
std::cout << result2 <<'\n';
}

In my definition of simpler, the boost version is *considerably*
simpler ....... ;-)

regards
Andy Little

John Nagle

unread,
Jul 24, 2006, 10:59:47 AM7/24/06
to
It's a cute idea, but not too helpful, since it won't
catch arithmetic overflow. Doing that efficiently requires
compiler and language support, since you'll want to look
at hardware overflow flags you can't see from C++.

John Nagle

kwikius wrote:
> James Kanze wrote:
>
>>kwikius wrote:
>> > James Kanze wrote:
>>
>> >> Untested, but there's got to be a simpler solution.
>>
>> > http://www.boost.org/libs/numeric/conversion/doc/index.html
>>
>>When I look at the paragraph "Range Checking Logic", in the
>>documentation, I'm not sure that they've found a simpler
>>solution.

---

Greg Herlihy

unread,
Jul 24, 2006, 11:01:18 AM7/24/06
to

(long solution omitted)
>

> Untested, but there's got to be a simpler solution.

How about:

assert( static_cast<Source>( static_cast<Target>(x)) == x );

?

Greg

ThosRTanner

unread,
Jul 24, 2006, 11:00:06 AM7/24/06
to

James Kanze wrote:
> ThosRTanner wrote:
>
> > Mind you C++ with an IDE is also a much better language than
> > C++ with an editor.
>
> And what is C++ with an IDE other than C++ with a particular
> editor imposed on you? If that editor happens to be better than
> the one you would otherwise use, it's an improvement. If not,
> it's anything but an improvement.

My experience with IDEs is that they provide
a) "Integrated" compilation which takes you to the point of an error on
compilation
b) Code completion so that
i) when you are using an object of a particular class, you can select
an available method or member of the class
ii) syntax validation (or syntax deduction) when typing the code.
c) Easier source modification when debugging

I realise that some editors and debuggers tend towards the
functionality of IDEs, but generally IDE's do it better. And most IDEs
can have their editing behaviour customised.

I am an incredibly bad typist, so anything that can reduce my level of
mistakes is all to the good

Greg Herlihy

unread,
Jul 24, 2006, 4:44:00 PM7/24/06
to

"Krzysztof Zelechowski" wrote:
> Uzytkownik "kanze" <ka...@gabi-soft.fr> napisal w wiadomosci
> news:1153126683.2...@35g2000cwc.googlegroups.com...
> > "Krzysztof Zelechowski" wrote:
> >> assert(Target(x) == x);
> >
> > You may get an implementation defined signal before the assert
> > trips (which probably doesn't matter). You may also fail to
> > trip even when you should, if the conversion is between signed
> > and unsigned types, e.g. Target is unsigned int, Source is int,
> > and the value of x is -3.
> >
>
> My code should be used when the compiler issues a warning. Should there be
> a warning about an implicit cast from int to unsigned int, my code would
> fail. But the OP wanted to handle a warning about truncation.

It is also possible when converting from one numeric type to another to
have an assertion detect either value truncation or a signed/unsigned
value mismatch between the original and converted value. The key is to
have the assertion perform the comparison with a numeric type of
sufficient range and resolution to resolve the inequality (in other
words, a long double):

typedef long double LongDouble;
...
assert( LongDouble(x) == LongDouble( Target(x)));

Greg

kwikius

unread,
Jul 25, 2006, 1:21:16 AM7/25/06
to
John Nagle wrote:
> It's a cute idea, but not too helpful, since it won't
> catch arithmetic overflow. Doing that efficiently requires
> compiler and language support, since you'll want to look
> at hardware overflow flags you can't see from C++.

I have exactly this problem at the monent as it happens.

The Quan library can be seen at one level as a wrapper class for
(usually) an inbuilt type.
It performs checks on calculations on physical quantities.
http://sourceforge.net/projects/quan.

Seeing as it performs these checks it would be useful for the library
also to perform checks for overflow too.

For the case of int Op int my current solution is to, by default, cast
the operands to a floating point type, do the calculation and then cast
the result back using boost::numeric::converter ( which throws
exceptions on overflow), but give the user the option to switch that
off and just do the raw int Op int calculation.

Even there there are problems. For example,the round trip from long to
float and back can, in a corner case, cause the return to be of a
different value to the original dependent on what long and float
actually consist of IIRC.

And floating point operations and what happens in case of overflow are
implementation dependent in C++ or whatever the phrase is. It would
sure be nice to have some types available which provide a precise
specification for what are acceptable values, independent of the
hardware and consistent behaviour too. It would also be nice to be able
to trap integer overflow without the need for these casts. The goal
being a library where I can make absolute guarantees regarding safe
values without specifying that the library does X on hardware Y and E
on hardware B. AFAIC Java has made good headway in that direction. I
know the results arent perfect, but I appreciate the intent.

The benefits for industry, safety critical applications and financial
calulations should be obvious.

regards
Andy Little

James Kanze

unread,
Jul 30, 2006, 3:37:45 PM7/30/06
to
kwikius wrote:
> James Kanze wrote:
>> kwikius wrote:
>> > James Kanze wrote:

>> >> Untested, but there's got to be a simpler solution.

>> > http://www.boost.org/libs/numeric/conversion/doc/index.html

>> When I look at the paragraph "Range Checking Logic", in the
>> documentation, I'm not sure that they've found a simpler
>> solution.

> Don't know quite how to put this, but their solution must be
> simpler, since it actually works. Heres a quick test of your
> solution, tried in VC7.1 and gcc4.0

Actually works doesn't necessarily mean simpler. The original
suggestion I was responding to was far, far simpler than
anything in Boost or that I have proposed. It didn't work for
negative values, of course, but it was simple.:-)

For the rest, I don't doubt that the solution in Boost works; it
wouldn't have made it into Boost if it hadn't. It even treats a
number of issues that hadn't even occured to me, like rounding
mode. (It's also well documented, which for publicly available
code outside of Boost is rather exceptional.)

> int main()
> {
> int result1 =
> numeric_cast<int>(static_cast<double>(std::numeric_limits<int>::max()));
> std::cout << result1 <<'\n';
> int result2 =
> numeric_cast<int>(static_cast<double>(std::numeric_limits<int>::max())
> + 1);
> std::cout << result2 <<'\n';
> }

> In my definition of simpler, the boost version is *considerably*
> simpler ....... ;-)

I'm not sure what point you're trying to argue. If you mean
using a working solution from Boost is a lot simpler than
writing one of your own which probably doesn't work for a few
corner cases, then I fully agree. Using working code written by
someone else is always simpler than trying to develop something
on your own.

I was talking not about use in a project, but about the
implementation. I would be very surprised that the internal
implementation of Boost was very simple, given all of the issues
that the explicitly address.

--
James Kanze kanze...@neuf.fr
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

---

James Kanze

unread,
Jul 30, 2006, 3:38:10 PM7/30/06
to
Greg Herlihy wrote:
> James Kanze wrote:

>> Untested, but there's got to be a simpler solution.

> How about:
>
> assert( static_cast<Source>( static_cast<Target>(x)) == x );

> ?

Full of implementation defined behavior. Where Source is a
floating point type, and Target an integral type, it will core
dump on a lot of implementations.

--
James Kanze kanze...@neuf.fr
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

---

James Kanze

unread,
Jul 30, 2006, 3:38:30 PM7/30/06
to

The whole point of the verifications is to avoid doing
Target(x), which may have implementation defined behavior, and
in fact core dumps for some values and some Target types on may
systems.

--
James Kanze kanze...@neuf.fr
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

---

James Kanze

unread,
Jul 30, 2006, 4:03:58 PM7/30/06
to
ThosRTanner wrote:
> James Kanze wrote:
>> ThosRTanner wrote:

>> > Mind you C++ with an IDE is also a much better language than
>> > C++ with an editor.

>> And what is C++ with an IDE other than C++ with a particular
>> editor imposed on you? If that editor happens to be better than
>> the one you would otherwise use, it's an improvement. If not,
>> it's anything but an improvement.

> My experience with IDEs is that they provide
> a) "Integrated" compilation which takes you to the point of an error on
> compilation

That's a feature of the editor. All of the editors I'm aware of
have it.

> b) Code completion so that
> i) when you are using an object of a particular class, you can select
> an available method or member of the class

That's also a feature of the editor. All of the editors I'm
aware of have an automatic completion feature. On the other
hand, they generally don't understand C++ grammar and scoping
rules, so the completion set is all visible symbols, and not
just the symbols which would be legal in a C++ program at this
point.

I'm still up in the air with regards to the advantages of this.
It's certainly a plus that, having typed std::v, completion
finds vector, and nothing else. For user defined symbols, on
the other hand, it's less clear; it's certainly not rare for me
to conceptually add a member variable to a class because I need
it, and to start using it in the functions, before I've actually
edited the class definition to include it.

> ii) syntax validation (or syntax deduction) when typing the code.

Again, most editors have this to some degree, e.g. matching
braces, automatic indentation, etc. Does syntax validation
beyond this point help that much? (It could, of course. When
you define a local variable which is in fact a function
declaration, for example, a really C++ aware editor could point
this out, and request confirmation. In the end, however, it's
not a question of IDE or not; it's a question of how much C++
the editor knows.)

> c) Easier source modification when debugging

I'll admit that I don't get this one. How does the editor play
a role here? You have a log file and a post-mortem (core dump
or whatever), which you analyse with various tools. Does the
IDE understand your log file format, to be able to position you
directly at the line which produced the log? (The best I've
seen in non-IDE editors is that you position the cursor on the
filename in one window, enter a command, and a second window
opens on that file. Although it should be possible to create a
command script in vim which would parse something like
[abc.cc:123] to open a new frame at line 123 of file abc.cc.)

> I realise that some editors and debuggers tend towards the
> functionality of IDEs, but generally IDE's do it better. And
> most IDEs can have their editing behaviour customised.

It's probably true that most special purpose IDE editors
understand more C++ than general purpose editors line vim or
emacs. On the other hand, they seem to be missing a number of
other features, many of which are, at least for me, more
important. (And of course, not a few IDE's use an external
editor.)

But that's what I said to begin with: the choice is the editor.
If the IDE provides a better editor, it is a win. If it
doesn't, it isn't (and I can't be bothered with the Unix IDE's
which use vim or emacs as their editor---I don't see any
advantage in them compared to using vim or emacs directly).

> I am an incredibly bad typist, so anything that can reduce my
> level of mistakes is all to the good

Any thing that can reduce the number of typing errors is all to
the good. Unless you're such a good typist that you never make
mistakes. And I don't think that anyone is that good.

--
James Kanze kanze...@neuf.fr
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

---

Greg Herlihy

unread,
Jul 31, 2006, 1:13:03 PM7/31/06
to

Then the concern is overblown. As long as Target(x) is not undefined,
than the expression is perfectly safe and will have either an
implementation-defined or a well-defined value - (in no event would it
ever have implementation-defined "behavior"). Furthermore, while a
program could test numeric_limits<Target>::traps to determine whether
the Target type traps at all, it is not even necessary in this case.
There is no chance that initializing a Target type with a valid numeric
value could ever trap - since only arithmetic operations can trap.
Initialization is not an arithmetic operation.

After all, if 70 lines of highly specialized template code are needed
just to determine whether converting a floating point to integer value
wouldn't core dump in C++, who in their right mind would ever decide to
write a numerical program in C++?

Greg

ThosRTanner

unread,
Jul 31, 2006, 1:13:34 PM7/31/06
to

James Kanze wrote:
> ThosRTanner wrote:
> > James Kanze wrote:
> >> ThosRTanner wrote:
>
> >> > Mind you C++ with an IDE is also a much better language than
> >> > C++ with an editor.
>
> >> And what is C++ with an IDE other than C++ with a particular
> >> editor imposed on you? If that editor happens to be better than
> >> the one you would otherwise use, it's an improvement. If not,
> >> it's anything but an improvement.
>
> > My experience with IDEs is that they provide
> > a) "Integrated" compilation which takes you to the point of an error on
> > compilation
>
> That's a feature of the editor. All of the editors I'm aware of
> have it.

I use nedit, and I haven't worked out how to make it do that yet.
Therefore I don't think it's true to say that all editors have that
feature. However, I know that all IDE's do.

PS I hate emacs and vim.

> > b) Code completion so that
> > i) when you are using an object of a particular class, you can select
> > an available method or member of the class
>
> That's also a feature of the editor.

It's always a feature of (the editor in) an IDE. Not always of an
editor.

> All of the editors I'm
> aware of have an automatic completion feature. On the other
> hand, they generally don't understand C++ grammar and scoping
> rules, so the completion set is all visible symbols, and not
> just the symbols which would be legal in a C++ program at this
> point.

I don't think that's much help. Certainly in our ghastly software,
where nearly every conceivable combination of characters is accessible
from the global namespace...

> I'm still up in the air with regards to the advantages of this.
> It's certainly a plus that, having typed std::v, completion
> finds vector, and nothing else. For user defined symbols, on
> the other hand, it's less clear; it's certainly not rare for me
> to conceptually add a member variable to a class because I need
> it, and to start using it in the functions, before I've actually
> edited the class definition to include it.

Umm. I'd edit the class first in that case - if only because I know
I'll get compilation errors if I don't edit it because I'll forget
otherwise. Anyway, in a decent editor, it'd just mean you had to type
it out in full till you've provided a definition (again, in an IDE I'd
expect something like 'create declaration for xxxx in class/on stack/'
options to appear fairly quickly)

> > ii) syntax validation (or syntax deduction) when typing the code.
>
> Again, most editors have this to some degree, e.g. matching
> braces, automatic indentation, etc.

That's not so much help, except when typing in, and the automatic
indentation works the way I like to indent code (almost invariably
never). I sort of meant like some editors/IDEs do, like on typing
if<space> they work out you are likely to then type (, ) ( and } in
short order, so do it for you and let you fill the spaces in.

> Does syntax validation
> beyond this point help that much? (It could, of course. When
> you define a local variable which is in fact a function
> declaration, for example, a really C++ aware editor could point
> this out, and request confirmation. In the end, however, it's
> not a question of IDE or not; it's a question of how much C++
> the editor knows.)

> > c) Easier source modification when debugging
>
> I'll admit that I don't get this one. How does the editor play
> a role here?

As in when using the IDE to step through source code (debugging
existing code,
rather than debugging from core file - though really I'd hope an IDE
/could/ debug from a core file). It's the debug, look at variables,
find line in error, change line, rebuild code, substitute new code in
executable and carry on debugging from where you were.

OK, that can be tricky, but I've seen it done from time to time with
varying levels of success. But ONLY in IDEs - never in editors, or
debuggers.

> You have a log file and a post-mortem (core dump
> or whatever), which you analyse with various tools. Does the
> IDE understand your log file format, to be able to position you
> directly at the line which produced the log? (The best I've
> seen in non-IDE editors is that you position the cursor on the
> filename in one window, enter a command, and a second window
> opens on that file. Although it should be possible to create a
> command script in vim which would parse something like
> [abc.cc:123] to open a new frame at line 123 of file abc.cc.)
>
> > I realise that some editors and debuggers tend towards the
> > functionality of IDEs, but generally IDE's do it better. And
> > most IDEs can have their editing behaviour customised.
>
> It's probably true that most special purpose IDE editors
> understand more C++ than general purpose editors line vim or
> emacs. On the other hand, they seem to be missing a number of
> other features, many of which are, at least for me, more
> important. (And of course, not a few IDE's use an external
> editor.)
>
> But that's what I said to begin with: the choice is the editor.
> If the IDE provides a better editor, it is a win. If it
> doesn't, it isn't (and I can't be bothered with the Unix IDE's
> which use vim or emacs as their editor---I don't see any
> advantage in them compared to using vim or emacs directly).

Well, I think the development environment isn't just the editor. Given
a development environment with a reasonable editor/debugger with
reasonable integration between editor and source code, or good
editor/reasonable debugger/no integration, I'd probably go for the
integrated environment. However if it had an editor I couldn't work
with even if I was paid the same as a footballer, then I'd think
differently. As I hate emacs / vim, I guess my perspective might be a
little different to yours ;-)

> > I am an incredibly bad typist, so anything that can reduce my
> > level of mistakes is all to the good
>
> Any thing that can reduce the number of typing errors is all to
> the good.

Didn't I just say that?

> Unless you're such a good typist that you never make
> mistakes. And I don't think that anyone is that good.

When I worked in a printing firm, their compositors were required to
achieve 99.9% accuracy. That works out at about 1 typo per page of book
I think. Secretarial courses only required 95%. I don't think I achieve
even that at first hit.

kuy...@wizard.net

unread,
Jul 31, 2006, 2:26:00 PM7/31/06
to
James Kanze wrote:
> ThosRTanner wrote:
.
> > My experience with IDEs is that they provide
> > a) "Integrated" compilation which takes you to the point of an error on
> > compilation
>
> That's a feature of the editor. All of the editors I'm aware of
> have it.

The environment you work in sounds quite different from the ones I've
used. The only editors I'm aware of with that feature are parts of
IDEs. The main editor I use is vi, and it doesn't seem to have that
feature.

.


> > i) when you are using an object of a particular class, you can select
> > an available method or member of the class
>
> That's also a feature of the editor. All of the editors I'm
> aware of have an automatic completion feature.

I've only seen that feature in editors that were part of an IDE.

.
> > ii) syntax validation (or syntax deduction) when typing the code.
>
> Again, most editors have this to some degree, e.g. matching
> braces, automatic indentation, etc.

Again, I've only seen that in IDE editors.

James Dennett

unread,
Aug 1, 2006, 2:17:15 AM8/1/06
to

The problem is the undefined cases.

> Furthermore, while a
> program could test numeric_limits<Target>::traps to determine whether
> the Target type traps at all, it is not even necessary in this case.
> There is no chance that initializing a Target type with a valid numeric
> value could ever trap - since only arithmetic operations can trap.
> Initialization is not an arithmetic operation.

Conversion, however, is. It's not storing the result of the
conversion that's the problem; it's doing the conversion in
the first place.

> After all, if 70 lines of highly specialized template code are needed
> just to determine whether converting a floating point to integer value
> wouldn't core dump in C++, who in their right mind would ever decide to
> write a numerical program in C++?

That's the kind of care that is needed to write completely
portable numeric code in C++ (or C), and the people who do
it well are those who understand this and take the care when
it's needed.

-- James

kanze

unread,
Aug 1, 2006, 1:36:21 PM8/1/06
to
ThosRTanner wrote:
> James Kanze wrote:
> > ThosRTanner wrote:
> > > James Kanze wrote:
> > >> ThosRTanner wrote:

> > >> > Mind you C++ with an IDE is also a much better
> > >> > language than C++ with an editor.

> > >> And what is C++ with an IDE other than C++ with a
> > >> particular editor imposed on you? If that editor
> > >> happens to be better than the one you would otherwise
> > >> use, it's an improvement. If not, it's anything but an
> > >> improvement.

> > > My experience with IDEs is that they provide
> > > a) "Integrated" compilation which takes you to the point of an error on
> > > compilation

> > That's a feature of the editor. All of the editors I'm
> > aware of have it.

> I use nedit, and I haven't worked out how to make it do that
> yet. Therefore I don't think it's true to say that all
> editors have that feature.

I said all of the editors I'm aware of. And I should have said
all of the *modern* editors I'm aware of; ed didn't have it.
(But I haven't used ed, outside of scripts, for around 20
years.) It's a feature of the editor; if your editor doesn't
have it, and it is an important feature, change the editor.

> However, I know that all IDE's do.

All of the editors in IDE's do seem to have it. But I don't see
the advantage the IDE brings compared to the editor alone.

> PS I hate emacs and vim.

So find another one. I don't care for emacs that much myself;
I've got vi in my fingers. (Personally, I don't like the editor
in Visual Studios. But that could easily be because I don't
know it that well. To the point that I don't even know how to
do the most fundamental things with it: piping a block of
text/code through an external program, for example, or doing a
global search and replace.)

> > > b) Code completion so that
> > > i) when you are using an object of a particular class, you can select
> > > an available method or member of the class

> > That's also a feature of the editor.

> It's always a feature of (the editor in) an IDE. Not always of
> an editor.

Some editors have the feature, some don't. If a particular
feature is important to you, obviously, then that becomes part
of your criteria for choosing an editor.

A good IDE, of course, will let you choose your editor. A good
editor will have hooks so that it can be integrated into an IDE.
The choice of an editor should be independant of whether you are
using an IDE or not.

> > All of the editors I'm aware of have an automatic completion
> > feature. On the other hand, they generally don't understand
> > C++ grammar and scoping rules, so the completion set is all
> > visible symbols, and not just the symbols which would be
> > legal in a C++ program at this point.

> I don't think that's much help. Certainly in our ghastly
> software, where nearly every conceivable combination of
> characters is accessible from the global namespace...

It helps, but admittedly because of the heuristics used to
search for the completion, which favors 1) nearby symbols, 2)
symbols in the same file, and 3) symbols in recently visited
files. It's not perfect, and after std::vector<X>::i,
completion will probably give you if, and not iterator, which is
obviously a better choice. But I've not found the difference to
be significant.

> > I'm still up in the air with regards to the advantages of
> > this. It's certainly a plus that, having typed std::v,
> > completion finds vector, and nothing else. For user defined
> > symbols, on the other hand, it's less clear; it's certainly
> > not rare for me to conceptually add a member variable to a
> > class because I need it, and to start using it in the
> > functions, before I've actually edited the class definition
> > to include it.

> Umm. I'd edit the class first in that case - if only because I
> know I'll get compilation errors if I don't edit it because
> I'll forget otherwise. Anyway, in a decent editor, it'd just
> mean you had to type it out in full till you've provided a
> definition (again, in an IDE I'd expect something like 'create
> declaration for xxxx in class/on stack/' options to appear
> fairly quickly)

It's probably possible to add such functionality to vim; it's
certainly possible to add it to emacs. My point is that it is
functionality of the editor which is embedded in the IDE, not of
the fact you are using an IDE. Now, you may prefer the editors
present in your IDE. That's a different question---if I had to
choose between vim in an IDE and emacs outside, for example, I'd
use the IDE. But the difference isn't IDE vs. no IDE; the
difference is between two editors. The IDE as such brings me
nothing.

> > > ii) syntax validation (or syntax deduction) when typing
> > > the code.

> > Again, most editors have this to some degree, e.g. matching
> > braces, automatic indentation, etc.

> That's not so much help, except when typing in, and the
> automatic indentation works the way I like to indent code
> (almost invariably never). I sort of meant like some
> editors/IDEs do, like on typing if<space> they work out you
> are likely to then type (, ) ( and } in short order, so do it
> for you and let you fill the spaces in.

I'd have to see it to see whether I liked it. I did use a
package for emacs once which did something similar, for Java.
It wasn't that bad, but it didn't bring enough to make me prefer
emacs over vim.

> > > c) Easier source modification when debugging

> > I'll admit that I don't get this one. How does the editor play
> > a role here?

> As in when using the IDE to step through source code
> (debugging existing code, rather than debugging from core file
> - though really I'd hope an IDE /could/ debug from a core
> file). It's the debug, look at variables, find line in error,
> change line, rebuild code, substitute new code in executable
> and carry on debugging from where you were.

That's more complicated. I'll admit that I rarely if ever step
through code; I can't see the point of it. (But there are
exceptions, particularly when trying to debug someone else's
code.) That is the sort of thing I understand by an IDE: the
editor's involved, but so are the compiler, the linker, the
debugger, and perhaps other tools. All "integrated". I'm
sceptical of this sort of development, however.

> OK, that can be tricky, but I've seen it done from time to
> time with varying levels of success. But ONLY in IDEs - never
> in editors, or debuggers.

Because, of course, it does require recompiling the code (which
the editor can't do, at least not directly), relinking it, and
getting the debugger to use the new version when it continues.
The Sun IDE supports it, but I've never used it.

[...]


> > But that's what I said to begin with: the choice is the
> > editor. If the IDE provides a better editor, it is a win.
> > If it doesn't, it isn't (and I can't be bothered with the
> > Unix IDE's which use vim or emacs as their editor---I don't
> > see any advantage in them compared to using vim or emacs
> > directly).

> Well, I think the development environment isn't just the editor.

Certainly not. You need awk and sed:-). (Seriously, of course,
you need a compiler/linker. In addition, tools like Rational
Rose are invaluable, and definitly some sort of source code
control. But a good scripting language is essential as well.)

> Given a development environment with a reasonable
> editor/debugger with reasonable integration between editor and
> source code, or good editor/reasonable debugger/no
> integration, I'd probably go for the integrated environment.
> However if it had an editor I couldn't work with even if I was
> paid the same as a footballer, then I'd think differently. As
> I hate emacs / vim, I guess my perspective might be a little
> different to yours ;-)

I presume that emacs and vim are not the only powerful editors
around:-). Personally, you're the first person I've heard from
who hates both; the philosophies are so different that if you
hate one, you usually like the other. Emacs can be customized
to more or less resemble any other editor. (But it's not the
same thing.)

[...]


> > Unless you're such a good typist that you never make
> > mistakes. And I don't think that anyone is that good.

> When I worked in a printing firm, their compositors were
> required to achieve 99.9% accuracy. That works out at about 1
> typo per page of book I think. Secretarial courses only
> required 95%. I don't think I achieve even that at first hit.

At first hit:-). The difference is that we are required to
achieve 100% accuracy. Since even the best can't do it at first
hit, all of our tools allow for corrections. (There's also the
question of time. You probably could achieve close to 100%
accuracy... at a rate of one character every 5 seconds. There's
such a thing as typing too fast; if correcting the additional
errors takes more time than you gained by typing faster, it's a
net loss.)

--
James Kanze GABI Software


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

skaller

unread,
Aug 1, 2006, 12:42:50 PM8/1/06
to
On Tue, 11 Jul 2006 12:38:15 +0000, Frederick Gotham wrote:

>
> This is mostly about my own personal taste, but still I'd like to express
> my opinion:

Lol!

> I'd like to suggest to the Committee that they use identifiers as short as
> possible for future additions to the standard.

[]

> In the current Standard, I particularly think the new-style casts are
> monstrosities:
>
> static_cast
> dynamic_cast
> reinterpret_cast
>

Well here's my take .. a lot of comments have been made here,
especially on casts.

(1) the choice of names for library functions which can be
namespace qualified is distinct from keywords.

(2) I personally hated the committee attitude -- prior to the
establishment of the first Standard -- trying to
to avoid new keywords. The same approach would make more sense now,
but clarity shouldn't be sacrificed by something as simple as a
keyword clashing with an identifier.

For example using 'auto' for variables whose type is deduced
is plain daft. The correct keyword to use is 'let' -- auto
has another meaning, even if it isn't used much, and it would
be used if C++ had lexically scoped nested functions
(to distinguish them from externs). WG21 can always follow
WG14 and use an identifier out of the reserved namespace
such as _Bool as a new keyword without much risk.

(3) The choice of long names for casts was quite deliberate.
What is more, the aim was to get rid of the need for C style
casts, and to formally deprecate them.

Unfortunately, the committee (including me) rejected the deprecation
proposal. There were two reasons:

(a) Break C compatibility
(b) Faulty decomposition of casts

The first is a clear reason, and a balance of the motto
"as close to C as possible but no closer".

I personally would have favoured breaking compatibility here,
but I accept the choice was political and the majority
opinion was reasonable.

Unfortunately, the C++ casts do not properly decompose all
the kinds of casts one needs, leading to some extremely
ugly casting sequences of dubious merit. To make it
clear **the idea was very good but it didn't pan out**.

For example, consider the conversion from long
to short. You might say this was a narrowing cast and thus
potentially dangerous. Yes. OK. Maybe it should even throw
an exception if the result destroys the value.

Well how about unsigned long to unsigned short?
Is that a narrowing cast?

The answer depends on your interpretation. If you view
unsigned types as just a local representation of
the natural numbers, then yes, it's a narrowing cast.

But on the other hand, if you view unsigned types as
modular arithmetic, modulo 2^n for some n, then this
is not so at all. Instead the cast is an important
integral domain morphism -- NOT a narrowing cast.
I'm sure there are other uses related to bit vectors.

On the other hand, some people contended that the
conversion double -> float was a narrowing cast.
But they're sometimes wrong, just as above. On the contrary,
for some algorithms, it is the other way around.
For example when you're testing the convergence
of a sequence to a limit, and you want 'as much
precision as possible', you often check for

| l - v | = 0

as a reliable way of calculating the real value

| l - v | < e

for an e close to zero. In this
case, converting the type of e = 0 from double to float
is anything but a narrowing conversion: in fact it
will cause the algorithm to terminate much earlier,
possibly leading to an entirely wrong result, on the
other hand you may actually WANT to use a float,
rather than a double, because you want precision
'up to float precision' and fear that a double(0)
would actually lead to cyclic behaviour (or even
divergence!).

So actually truth is you simply cannot generalise about
what a 'narrowing' conversion actually is: for signed
integers it is one that risks overflow, but for unsigned
it may or may not lead to a possible loss of 'precision',
and for floating point the whole idea is bogus: you're
actually converting to a distinct representation with
a numerically complex operation, and all you can REALLY
say is that the exponent might overflow. You actually
CANNOT say the loss of bits in the mantissa results
in a loss of precision .. because the value may have
been calculated in such a way it only had 1 digit
of precision in the first place.

So .. already with arithmetic casts, it isn't even close
to being clear there is any way to simply factor the
casts.

Then, as someone else pointed out, using 'static_cast'
for a safe derived to base conversion is clearly overkill,
we needed 'implicit_cast' but didn't get it: the conversion
is sometimes needed to chose the right overload, and sometimes
desirable to be very specific you're abstracting a class
type "right here" to prevent the derived type being
widely known.

Then there is 'const cast'. Seems simple.. but where
is volatile cast? I could go on about reinterpret cast,
which isn't actually what it suggests .. it's a conversion,
even when applied to references. And it's idea not to
throw away const is entirely bogus!


And there's no way to cast 'lvalueness' although you can do
it easily with a function, which shows how brain dead the C++
type system really is:

// convert an rvalue to an lvalue
template<typename T>
const &lvalue(T const &x) { return x; }

and thence:

// this reinterpret cast works with rvalues too
template<typename T, typename U>
T &reinterpret(U const &x) {
return reinterpret_cast<T&>(const_cast<U&>(x));
}

which is perfectly typesafe when applied to an rvalue .. but
not when applied to an arbitrary lvalue!! After all, rvalues
are of non-const type .. you can do:

X().modifier()

which is the reason rvalues were declared non-const in the
first place (motivation by Dag Bruck, Sweden).

Finally note 'function style casts' degenerate badly:

int(1L) // a conversion
X(1) // constructor
(void*)(p) // err is this a function cast or a C cast?
typedef void *voidp;
voidp(p) // oh we wanted a function style cast
// but couldn't have one without a typedef .. arrggg

What it comes down to is that given a severely broken
type system, properly factoring the casts to cover all
bases simply wasn't assured .. it just wasn't worth the risk
to throw out the C style casts, particularly considering
that they're usually terser.

Except in special cases such as the templates above where
I want to be very precise, and the usage is wrapped in a
template anyhow, I always use C style casts. I *would have
preferred C++ casts* if they'd properly factored the possible
intents, and been a bit easier to compose. The problem,
quite simply, is not with the casts, but the type system
they're supposed to work with.

So .. IMHO .. the new style casts are worthwhile addition
to the language but they do NOT cover all the bases succinctly
enough for anyone to claim that using C style casts is
bad style.

BTW: I regularly use a programming language without
casts .. more precisely there are coercions, but they're
always type safe. The difference is .. the language has
a decent type system to start with, and real casts are
only needed VERY rarely. Basically you aren't allowed
to break the type system (the reinterpret casts that
are provided are not documented, and can cause severe
problems for the garbage collector if abused).

So it is certainly possible to design a language with
a strong enough type system that casts aren't required ..
but C++ is not that language .. for better or
worse we still need casts.


--
John Skaller <skaller at users dot sf dot net>
Try Felix, the successor to C++ http://felix.sf.net

kanze

unread,
Aug 1, 2006, 1:43:50 PM8/1/06
to

That's not what the standard says. The C++ standard is rather
vague about what could happen, but the C standard is very clear:
either an implementation defined value, or an
implementation-defined signal.

In practice, I suspect that on most modern implementations, it
will depend on the settings of the FPU: C99 requires the
presence of an option for trapping, and it would be surprising
if implementations of C++ didn't offer it as well.

> Furthermore, while a program could test
> numeric_limits<Target>::traps to determine whether the Target
> type traps at all, it is not even necessary in this case.
> There is no chance that initializing a Target type with a
> valid numeric value could ever trap - since only arithmetic
> operations can trap.

The standard says differently. At least, it says that the
conversion may raise an implementation defined signal.

> Initialization is not an arithmetic operation.

> After all, if 70 lines of highly specialized template code are
> needed just to determine whether converting a floating point
> to integer value wouldn't core dump in C++, who in their right
> mind would ever decide to write a numerical program in C++?

Maybe those who understand the language, and know how to use it
for there applications. Or those who want the machine to trap
on an error condition. If you know the types involved, it's
very easy to write the code. The problem is to write it
generically without knowledge of the types, and correctly handle
all of the oddities concerning unsigned and signed comparisons
and promotions.

--
James Kanze GABI Software

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

kanze

unread,
Aug 1, 2006, 1:44:51 PM8/1/06
to
kuy...@wizard.net wrote:
> James Kanze wrote:
> > ThosRTanner wrote:

> > > My experience with IDEs is that they provide
> > > a) "Integrated" compilation which takes you to the point of an error on
> > > compilation

> > That's a feature of the editor. All of the editors I'm aware of
> > have it.

> The environment you work in sounds quite different from the
> ones I've used. The only editors I'm aware of with that
> feature are parts of IDEs. The main editor I use is vi, and it
> doesn't seem to have that feature.

I should have said *modern* editors. It's true the vi doesn't
have this; nor does ed. Vim and emacs do, however---vim is
largely compatible with vi, and emacs has a viper mode which
more or less emulates vi, so why not change? (If you're under
Linux, when you request vi, you typically get vim anyway.)

I'm curious what kind of environment you work in. vi is a
typical Unix editor---the only times I've seen it elsewhere have
been with Unix emulation kits (MKS ToolKit, UWin, etc.). And a
typical Unix today comes with not only vi (and ed), but also
emacs, and sometimes vim as well. (The Sun development
environment comes with both emacs and vim, and uses them as the
editor in its IDE.)

> .
> > > i) when you are using an object of a particular class, you can select
> > > an available method or member of the class

> > That's also a feature of the editor. All of the editors I'm
> > aware of have an automatic completion feature.

> I've only seen that feature in editors that were part of an IDE.

Well, vim and emacs often are part of an IDE. But the features
are part of the editor, and are there, IDE or not.

> .
> > > ii) syntax validation (or syntax deduction) when typing the code.

> > Again, most editors have this to some degree, e.g. matching
> > braces, automatic indentation, etc.

> Again, I've only seen that in IDE editors.

Come now, even vi had that. Twenty years ago. Not to the
degree you get today, of course, but matching parentheses,
braces, etc., and automatic indention (not syntax dependant)
where there.

Still, I'd say that the syntax dependant automatic indention of
vim or emacs is probably the single one feature I depend most
on. Hit return at the end of a statement, and the cursor
positions itself in the wrong column, and you know right away
you've screwed something up: mismatches a parentheses, forgotten
a semi-colon, or something along those lines.

None of them to date handles matching <...> for templates. And
I suspect that they won't very soon; unlike (...), [...] and
{...}, the < and the > aren't necessarily bracing, and
determining when they are, and when they are just less than or
more than, requires a lot more knowledge of C++ than any general
purpose editor is likely to have anytime soon.

--
James Kanze GABI Software

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

Fernando Cacciola

unread,
Aug 2, 2006, 5:57:13 PM8/2/06
to
Greg Herlihy wrote:
> [...]

> After all, if 70 lines of highly specialized template code are needed
> just to determine
>
If "70 lines of highly specialized template code" refers to the boost
implementation then you should know that the purpose of that code is not
just to determine if a conversion is in range for a target type but also
to perform the range check as efficiently as possible.
For example, if you convert an "unsigned" to an "int" then the actual range
checking tests only for negative values; and if you convert an "int" to a
"double" then a runtime range check is totally ellided.

A big part of the code complextity in the boost implementation comes from
deciding at compile time whether runtime range checking is actually needed,
and if it is what exactly is minimally required.


> whether converting a floating point to integer value
> wouldn't core dump in C++
>

If the conversion core dumps then a checked conversion is probably unneeded.
The real practical problem ocurrs when the conversion silently fails,
truncating, or even worse, warpping around, the result.

> who in their right mind would ever decide
> to write a numerical program in C++?


Well, I have been writing numerical programs in C++ for a decade and a half
now FWIW
But then none of my friends would say I'm in my right mind though

Fernando Cacciola
SciSoft
http://fcacciola.50webs.com/

John Nagle

unread,
Aug 8, 2006, 8:02:28 AM8/8/06
to
skaller wrote:
> On Tue, 11 Jul 2006 12:38:15 +0000, Frederick Gotham wrote:
>>In the current Standard, I particularly think the new-style casts are
>>monstrosities:
>>
>> static_cast
>> dynamic_cast
>> reinterpret_cast
>>

If you use reinterpret_cast too much, you're doing something wrong.
On the other hand, dynamic_cast, which is safe, should be used more.

> For example using 'auto' for variables whose type is deduced
> is plain daft. The correct keyword to use is 'let' -- auto
> has another meaning, even if it isn't used much, and it would
> be used if C++ had lexically scoped nested functions
> (to distinguish them from externs).

I agree. It will break occasional code in an obvious way (programs
won't compile), but "let" would be much clearer to programmers.
And someday we might want to put in lexically scoped functions.
GCC, after all, has them as an extension.

> (3) The choice of long names for casts was quite deliberate.
> What is more, the aim was to get rid of the need for C style
> casts, and to formally deprecate them.

That really should have been done by now. Casts are
such a common source of bugs that making them highly
visible and explicit is a win from a reliablity standpoint.

> The answer depends on your interpretation. If you view
> unsigned types as just a local representation of
> the natural numbers, then yes, it's a narrowing cast.
>
> But on the other hand, if you view unsigned types as
> modular arithmetic, modulo 2^n for some n, then this
> is not so at all. Instead the cast is an important
> integral domain morphism -- NOT a narrowing cast.
> I'm sure there are other uses related to bit vectors.

The semantics of "unsigned" tend to be something that
most programmers don't think about too hard. In the
initial release of 4.3BSD, due to a poorly chosen cast,
TCP sequence number arithmetic was broken for the upper
half of the sequence number space. That took me three
days to find and fix, and I had to look at the generated
machine code to be sure of what was happening. (My name
is in the 4.3BSD release notes for that one.)

Actually, the idea that unsigned values have modular
arithmetic is kind of wierd. What should have been done
is to deal with the types of intermediate expressions
numerically, rather than syntactically, while recommending
some optimizations for performance.

For example,

short i, j, k;
let x1 = i*j; // k is a long to avoid overflow
let kshort = short(i*j); // avoid expansion

int x2 = (i * j) / k; // (i * k) is a long.

But

int i;
i = i+1; // no expansion, because the result is immediately converted

And
unsigned short i;
i = (i + 1) % 65536; // Technically, this requires promotion to long,
// but should be optimized into unsigned arithmetic
// where supported by the hardware.

This approach gets you the same answers on all platforms. But it's too
late to put this into C++. Nevertheless, realize that trying to deal
with numeric types by syntatical means generally won't lead to consistent
numerical results.

John Nagle

SuperKoko

unread,
Aug 8, 2006, 9:05:05 AM8/8/06
to

Frederick Gotham wrote:
> The objective of the function is to increment a pointer by a specified
> number of bytes -- it's the client's problem if they end up with a pointer
> to a misaligned object.
>
> One plausible use of it would be, (assuming we have an "alignof" operator):
>
> AdvPtr(p, alignof(*p));
>
>
alignof is non-standard, thus, non-portable.
Though, there is tr1::alignment_of... I didn't thought of it, probably
because tr1 is not yet widely supported.

> > Back to your question:
> >> And again we have melodramatic use of "dangerous". There's nothing
> >> wrong with the way I use casts.
> >
> > The mere interface of your function is *dangerous*!
> > If the caller pass a non-correctly aligned "bytes" argument, it will
> > have non-portable, implementation-specific results.
>
>
> Which is why the caller shouldn't pass an incorrect value for "bytes".
>
> Is array indexing dangerous? Nothing's to stop me writing:
>
> int array[8];
>
> array[242] = 4;
>
>
> Quick! Let's ban array indexing!
>
My point was that it was very very low-level.
In fact, without tr1, the only usage that I can see is incrementation
with values multiple of sizeof(T).

I agree that with tr1 this function can make sense.

I just hope that this type of low-level thing occupy less than 5% of
your programs (except if you are developing drivers, OS kernels or such
low-level applications).

Frederick Gotham

unread,
Aug 8, 2006, 8:53:46 AM8/8/06
to
John Nagle posted:

> skaller wrote:
>> On Tue, 11 Jul 2006 12:38:15 +0000, Frederick Gotham wrote:
>>>In the current Standard, I particularly think the new-style casts are
>>>monstrosities:
>>>
>>> static_cast
>>> dynamic_cast
>>> reinterpret_cast
>>>
>
> If you use reinterpret_cast too much, you're doing something wrong.


Ridiculous assessment.

"Son, if you're using the brakes too much, you're not driving properly.",
How can the father say that if he hasn't seen the race track?


> On the other hand, dynamic_cast, which is safe, should be used more.


I've never used dynamic_cast, because I've never casted from a base class
to a derived class without knowing for certain that the base object was in
fact a derived object.



>> (3) The choice of long names for casts was quite deliberate.
>> What is more, the aim was to get rid of the need for C style
>> casts, and to formally deprecate them.
>
> That really should have been done by now. Casts are
> such a common source of bugs that making them highly
> visible and explicit is a win from a reliablity standpoint.


I've never introduced a bug by using casts. Never.

C-style casts are quite handy:

int Func()
{
long i = 5;

return (int)i;
/* Cast to suppress warning */
}

> short i, j, k;
> let x1 = i*j; // k is a long to avoid overflow


That would open a can of worms.

Both "i" and "j" are promoted to "int" (implementation-specific as to
whether signed or unsigned), and the result of the operation is an "int"
also (implementation-specific as to whether signed or unsigned).

If "x1" is to be a "long", this would have consequences on integer
promotion and so forth...

--

Frederick Gotham

AllanW

unread,
Aug 8, 2006, 1:23:22 PM8/8/06
to
James Kanze wrote:
> Untested, but there's got to be a simpler solution.

template <class Target, class Source>
inline Target numeric_cast(Source x)
{
Target y = static_cast<Target>(x);
Source z = static_cast<Source>(y);
assert(z==x);
return y;
}

Also untested, but certainly simpler...

AllanW

unread,
Aug 9, 2006, 8:32:31 AM8/9/06
to
> Frederick Gotham wrote:
> > Why should expert programmers be burdened with unwieldy names? It insults
> > human intelligence.

James Dennett wrote:
> Most good programmers accept that they make mistakes, and
> embrace tools and techniques that help to reduce the
> frequency of those mistakes.

Personally, I embrace SOME of these tools, but not all of them.

There was a computer language called CSP. I think it stood for
Cross-Systems Product; despite this, as far as I know it was only
ever implemented on IBM mainframes (but under multiple operating
systems). I don't know if this language is still in use, but I hope
not.

CSP was allegedly a "fourth-generation language" (this phrase too
seems to have died, possibly from being so overhyped that it lost
any semblance of meaning). But this particular language "helped"
the programmer by tying his hands, preventing him from making
certain mistakes.

What I find most memorable about this language was that it
prevented programmers from making procedures too complicated,
by limiting procedures to only one I/O statement. So even simple
programs with only 5 I/O statements, had to be written as 5
procedures calling each other.

Early in my career, this was the first programming language that
I ever worked on, that I didn't put on my résumé... I figured that if
knowing CSP would help me get a certain job, I didn't want that job.

kwikius

unread,
Aug 9, 2006, 11:12:14 AM8/9/06
to
AllanW wrote:
> James Kanze wrote:
> > Untested, but there's got to be a simpler solution.
>
> template <class Target, class Source>
> inline Target numeric_cast(Source x)
> {
> Target y = static_cast<Target>(x);
> Source z = static_cast<Source>(y);
> assert(z==x);
> return y;
> }
>
> Also untested, but certainly simpler...

It might be worth you guys trying this stuff out, and then saying its
simpler, meanwhile I am still happy to stick with
boost::numeric::converter:

#include <limits>
#include <cassert>
#include <iostream>

template <class Target, class Source>

inline Target numeric_cast(Source source)
{
Target target = static_cast<Target>(source);
Source back_to_source = static_cast<Source>(target);
std::cout << "source = " << source <<'\n';
std::cout << "target = " << target <<'\n';
std::cout << "back_to_source = " << back_to_source <<'\n';
// assert(back_to_source==source);
return target;
}

int main()
{
long v1 = std::numeric_limits<long>::max();
numeric_cast<float>(v1);
}

/*
output:
in VC7.1 32 bit windows

source = 2147483647
target = 2.14748e+009
back_to_source = -2147483648

output in gcc 32 bit windows

source = 2147483647
target = 2.14748e+09
back_to_source = -2147483648
*/


regards
Andy Little

Dave Thompson

unread,
Aug 14, 2006, 12:18:56 PM8/14/06
to
On Tue, 1 Aug 2006 11:43:50 CST, "kanze" <ka...@gabi-soft.fr> wrote:

> Greg Herlihy wrote:
> > James Kanze wrote:

<snip>


> > > The whole point of the verifications is to avoid doing
> > > Target(x), which may have implementation defined behavior,
> > > and in fact core dumps for some values and some Target types
> > > on may systems.
>
> > Then the concern is overblown. As long as Target(x) is not
> > undefined, than the expression is perfectly safe and will have
> > either an implementation-defined or a well-defined value - (in
> > no event would it ever have implementation-defined
> > "behavior").
>
> That's not what the standard says. The C++ standard is rather
> vague about what could happen, but the C standard is very clear:
> either an implementation defined value, or an
> implementation-defined signal.
>

Only between integer types, and only in C99 which postdates C++98.
For floating-point (and floating-point to integer) value outside
representable range is (still) Undefined Behavior in C99.
Most hardware I've seen either does produce some value
or a trap which might become a signal, but that's not required.

> In practice, I suspect that on most modern implementations, it
> will depend on the settings of the FPU: C99 requires the
> presence of an option for trapping, and it would be surprising
> if implementations of C++ didn't offer it as well.
>

Only for floating-point and only if the implementation claims to
support IEC 60559 aka IEEE which is optional. Hardware that supports
IEEE (or could) is common and getting more so, so _reasonable_
implementations should support it, but it's not required.

- David.Thompson1 at worldnet.att.net

James Kanze

unread,
Aug 15, 2006, 2:50:43 PM8/15/06
to
Fernando Cacciola wrote:
> Greg Herlihy wrote:
>> [...]
>> After all, if 70 lines of highly specialized template code
>> are needed just to determine

> If "70 lines of highly specialized template code" refers to
> the boost implementation then you should know that the purpose
> of that code is not just to determine if a conversion is in
> range for a target type but also to perform the range check as
> efficiently as possible. For example, if you convert an
> "unsigned" to an "int" then the actual range checking tests
> only for negative values; and if you convert an "int" to a
> "double" then a runtime range check is totally ellided.

> A big part of the code complextity in the boost implementation
> comes from deciding at compile time whether runtime range
> checking is actually needed, and if it is what exactly is
> minimally required.

Not just. I've not looked at it, but a large part of the
problem is avoiding the implicit conversions which take place,
causing (sometimes) signed values to be compared as unsigned,
etc. And dealing with the fact that std::numeric_limits<>::min
has different semantics for integral values and for floating
point.

>> whether converting a floating point to integer value wouldn't
>> core dump in C++

> If the conversion core dumps then a checked conversion is
> probably unneeded.

Agreed. The problem is that it doesn't, always. The problem is
that you don't really know, in advance, what it will do. (At
least not portably.)

--
James Kanze kanze...@neuf.fr
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

---

James Kanze

unread,
Aug 16, 2006, 12:23:49 PM8/16/06
to
Frederick Gotham wrote:
> John Nagle posted:

>> skaller wrote:
>>> On Tue, 11 Jul 2006 12:38:15 +0000, Frederick Gotham wrote:
>>>> In the current Standard, I particularly think the new-style
>>>> casts are monstrosities:
>>>> static_cast
>>>> dynamic_cast
>>>> reinterpret_cast

>> If you use reinterpret_cast too much, you're doing
>> something wrong.

> Ridiculous assessment.

Not really.

>> On the other hand, dynamic_cast, which is safe, should be
>> used more.

> I've never used dynamic_cast, because I've never casted from a
> base class to a derived class without knowing for certain that
> the base object was in fact a derived object.

I think John's point was that what you think you know may not
always be correct. I've noticed that the best programmers fill
their code with lots of asserts of things which they know are
true. Similarly, a dynamic_cast which returns a null pointer
will usually cause an immediate failure, whereas the static_cast
will cause a subtle error somewhere down the line.

>>> (3) The choice of long names for casts was quite deliberate.
>>> What is more, the aim was to get rid of the need for C style
>>> casts, and to formally deprecate them.
>> That really should have been done by now. Casts are
>> such a common source of bugs that making them highly
>> visible and explicit is a win from a reliablity standpoint.

> I've never introduced a bug by using casts.
> Never.

Except, of course, in the code you post in
comp.lang.c++.moderated.

[...]


>> short i, j, k;
>> let x1 = i*j; // k is a long to avoid overflow

> That would open a can of worms.

> Both "i" and "j" are promoted to "int"
> (implementation-specific as to whether signed or unsigned),
> and the result of the operation is an "int"

Both i and j are promoted to int, period. A short will never be
promoted to an unsigned. (The only time a "promotion" will
result in an unsigned is if the values of the source type do not
fit into an int. And the standard requires all of the values of
a short to be representable in an int.)

I'm not sure what the rest of the argument is. Presumably, x1
would have type int, here, since that is the type of the
expression i*j. I'm not sure where the k comes into it. But
your point concerning promotion causing confusion is valid in
general. Especially the fact that an unsigned short will act as
a signed on some implementations, and as an unsigned on others.

--
James Kanze kanze...@neuf.fr
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

---

David Abrahams

unread,
Aug 16, 2006, 12:26:59 PM8/16/06
to
kanze...@neuf.fr (James Kanze) writes:

> Fernando Cacciola wrote:
>
>> A big part of the code complextity in the boost implementation
>> comes from deciding at compile time whether runtime range
>> checking is actually needed, and if it is what exactly is
>> minimally required.
>
> Not just. I've not looked at it, but a large part of the
> problem is avoiding the implicit conversions which take place,
> causing (sometimes) signed values to be compared as unsigned,
> etc. And dealing with the fact that std::numeric_limits<>::min
> has different semantics for integral values and for floating
> point.

Since Fernando wrote the Boost implementation I think he knows "just"
what problems it's solving and how much size that contributes ;-D

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

0 new messages