casting A* to A& ?

S

Sigurd Stenersen

Tom said:
Depending on the relationship, the cast might cause a function to be
called

Well, that's where I'm arguing that you're not casting but rather
instantiating.

might need a cast pointer value to be adjusted (multiple
inheritence)

That's a good point and I didn't think of that. But in this case it could
be argued that with multiple inheritance, you get an implicit type
conversion operator and that you're not casting but rather that you're
calling this implicit operator. Further proof of this is that you can make
this operator explicit and it'll certainly be called.

or it might not need to do anything at runtime.

const_cast, static_cast and reinterpret_cast give you more control,
since each of them will only do a subset of what a C-style cast can
do.

Yes, I do realize that. You've almost convinced me that I should to start
using them...

All casts to non-reference types give you a temporary (or rvalue),
unless I'm mistaken.

int i;
(char) i;

No, I don't think so. The compiler will use the lvalue (i) for this.

The point is that what the cast dose is related to both source and
destination type, and the relationship between those types.

Yes, I can see that that is true with your perception of what a cast is.
And I also see that several skilled people on this newsgroup agree with you.

And I still feel like I have a valid point.
 
S

Sigurd Stenersen

Igor Tandetnik wrote:
[excellent explanation of C++ typecasts snipped]
That's what people mean when they say C-style cast is
context-sensitive - it behaves differently when casting between
related types than when casting between unrelated ones; it takes the
relation between the two types into account. Contrast this with
reinterpret_cast, which just blindly takes the bit layout as is, and
treats it as a different type.

I disagree with your conclusion - it's the C++ style casts that behave
differently depending on what you describe here, the C-style cast behaves
the same way all over the place.

In other words : when you keep changing the "measuring system" while
"measuring" you are quite likely to get different "results" for the same
"input"...
 
S

Sigurd Stenersen

Tom said:
To put it more precisely, the code is well-formed but exhibits
undefined behaviour.

....which it would not do, of course, if you knew what you were doing.


It's usually better to stick to the truth. Life is simpler that way. ;o)
 
S

Sigurd Stenersen

Tom said:
C-style casting to, say, a "std::string const&" might involve a
constructor call, a conversion operator call, a reference coercion, a
qualification adjustment or a no-op, depending on the source type. I
don't consider all of those to be the same thing!

My point precisely. It's only the NOP that actually *is* a C-style cast.
 
I

Igor Tandetnik

Sigurd Stenersen said:
Yeah. And now you're talking about something that's just not
possible to do with a C-style cast.

Is too:

class B {};
class D : public B {};

B* pB = new D();

D* pD1 = (D*)pB; // equivalent to static_cast

D* pD2 = (D*)(void*)pB; // equivalent to reinterpret_cast

The intermediate cast to void* is used here to lose context - the
relation between B and D. C-style cast (or more precisely, explicit type
conversion expression as defined in C++ standard 5.4) is
context-sensitive after all. It it were completely context-insensitive
and just "treat something of one type like it actually is some other
type", then it should be transitive, right (assuming there's no loss of
information due to casting to a smaller type)? But it's clearly not.
--
With best wishes,
Igor Tandetnik

"On two occasions, I have been asked [by members of Parliament], 'Pray,
Mr. Babbage, if you put into the machine wrong figures, will the right
answers come out?' I am not able to rightly apprehend the kind of
confusion of ideas that could provoke such a question." -- Charles
Babbage
 
T

Tom Widmer

Tom said:
Carl Daniel [VC++ MVP] wrote:
Tom is correct.

I didn't say he's wrong. I pointed out that the C-style cast does
the same thing no matter what you use it for.

C-style casting to, say, a "std::string const&" might involve a
constructor call, a conversion operator call, a reference coercion, a
qualification adjustment or a no-op, depending on the source type. I
don't consider all of those to be the same thing!

My point precisely. It's only the NOP that actually *is* a C-style cast.

They are all C-style casts. I think there is a difference of opinion
on what a C-style cast is, and this has lead to this whole argument. A
C-style cast is generally meant to refer to any expression of the
form:

(T) cast-expression

where T is a type. In other words, a C-style cast is synonymous with
what the C++ standard calls "Explicit type conversion (cast
notation)". Do you disagree?

Tom
 
I

Igor Tandetnik

Sigurd Stenersen said:
Igor Tandetnik wrote:
[excellent explanation of C++ typecasts snipped]
That's what people mean when they say C-style cast is
context-sensitive - it behaves differently when casting between
related types than when casting between unrelated ones; it takes the
relation between the two types into account. Contrast this with
reinterpret_cast, which just blindly takes the bit layout as is, and
treats it as a different type.

I disagree with your conclusion - it's the C++ style casts that behave
differently depending on what you describe here, the C-style cast
behaves the same way all over the place.

Can your formally define the assertion "behaves the same way" ? It
appears that the whole discussion keeps revolving around the fact that
you understand the term "the same way" differently than all other
participants.

Actually, before this discussion can continue, can you please formally
define the following:

1. The meaning of the term "C-style cast". Most participants understand
it as referring to a syntactical construct of Explicit type conversion
(cast notation), as defined in C++ standard 5.4. Yet you seem to argue
that it is a true C-style cast in some cases, and not really a C-style
cast in other cases.

2. How you believe a C-style cast, as defined by you in item 1, behaves
or should behave.

3. Your criterion for when behavior in one case is sufficiently similar
to that in antother case, so that you can say that something "behaves
the same way" in both cases.
In other words : when you keep changing the "measuring system" while
"measuring" you are quite likely to get different "results" for the
same "input"...

That's exactly why I would like you to formally establish a point of
reference, since yours appears to be quite unorthodox, to the point
where fundamental term definitions implicitly understood by most
participants can no longer be relied upon in the discussion. Thus I
would like them to be explicitly stated up front, then we can continue
discussion within your set of axioms.
--
With best wishes,
Igor Tandetnik

"On two occasions, I have been asked [by members of Parliament], 'Pray,
Mr. Babbage, if you put into the machine wrong figures, will the right
answers come out?' I am not able to rightly apprehend the kind of
confusion of ideas that could provoke such a question." -- Charles
Babbage
 
S

Sigurd Stenersen

Igor said:
Is too:

class B {};
class D : public B {};

B* pB = new D();

D* pD1 = (D*)pB; // equivalent to static_cast

D* pD2 = (D*)(void*)pB; // equivalent to reinterpret_cast

Yeah. And now you're talking about something that's just not
possible to do with a single C-style cast.
 
S

Sigurd Stenersen

Tom said:
They are all C-style casts. I think there is a difference of opinion
on what a C-style cast is, and this has lead to this whole argument.

Yes, that is my perception too.

A C-style cast is generally meant to refer to any expression of the form:

(T) cast-expression

where T is a type.

You have to take it a bit further.

Most C++ developers would agree that
(T) ce
means exactly the same as
T(ce)
and most of them would also label both as C-style casts.

And thus, if given
struct X { X(); }
then
X(ce)
is *not* a cast but an instantiation, and therefore
(X) ce
is not a cast but an instantiation.

I realize that "most developers" is by now probably reduced to "one
developer" in this newsgroup, but I still have a valid point...

In other words, a C-style cast is synonymous with
what the C++ standard calls "Explicit type conversion (cast
notation)". Do you disagree?

I don't know. I don't have the standard handy, and I really hate
formalities so let's not go there.
 
I

Igor Tandetnik

Sigurd Stenersen said:
Igor said:
Sigurd Stenersen said:
Carl Daniel [VC++ MVP] wrote:
For example, if you wanted to cast from base to derived but prevent
any change in value representation (this-pointer adjustments),
you'd have to use a reinterpret_cast, because in that context a
C-style cast will behave as a static_cast.

Yeah. And now you're talking about something that's just not
possible to do with a C-style cast.

Is too:

class B {};
class D : public B {};

B* pB = new D();

D* pD1 = (D*)pB; // equivalent to static_cast

D* pD2 = (D*)(void*)pB; // equivalent to reinterpret_cast

Yeah. And now you're talking about something that's just not
possible to do with a single C-style cast.

How is this observation related to the issue of whether C-style cast
behaves "the same way" or not? I fail to see your point. Can you please
elaborate (preferably after you answer my other post about establishing
the terminology)?
--
With best wishes,
Igor Tandetnik

"On two occasions, I have been asked [by members of Parliament], 'Pray,
Mr. Babbage, if you put into the machine wrong figures, will the right
answers come out?' I am not able to rightly apprehend the kind of
confusion of ideas that could provoke such a question." -- Charles
Babbage
 
S

Sigurd Stenersen

Igor said:
Sigurd Stenersen said:
Igor Tandetnik wrote:
[excellent explanation of C++ typecasts snipped]
That's what people mean when they say C-style cast is
context-sensitive - it behaves differently when casting between
related types than when casting between unrelated ones; it takes the
relation between the two types into account. Contrast this with
reinterpret_cast, which just blindly takes the bit layout as is, and
treats it as a different type.

I disagree with your conclusion - it's the C++ style casts that
behave differently depending on what you describe here, the C-style
cast behaves the same way all over the place.

Can your formally define the assertion "behaves the same way" ? It
appears that the whole discussion keeps revolving around the fact that
you understand the term "the same way" differently than all other
participants.

Now, now... Let's not get aggrevated here... ;o)

I think you've got it wrong. It's not the term "the same way" we disagree
on, it's the term "C-style cast".

Actually, before this discussion can continue, can you please formally
define the following:

I really hate formalities, but OK I'll give it a shot...

1. The meaning of the term "C-style cast". Most participants
understand it as referring to a syntactical construct of Explicit
type conversion (cast notation), as defined in C++ standard 5.4. Yet
you seem to argue that it is a true C-style cast in some cases, and
not really a C-style cast in other cases.

No, you're reading a bit too much into what I'm saying. I also think you
should be careful with your assumptions about what "most participants
understand" - you may be right, but you can't *know* this...

In my little brain, C++ is most of what C had and some rather nifty
additions. One of the nifty little additions is the various kinds of C++
style casts. And as C++ has it's own kind of casts, you could safely assume
that the old-fashioned C-style casts behave pretty much exactly the same way
as they do in C (even tho they may be a bit stricter, they still *function*
the same way).

Now, it's been a while since I wrote anything in C, but I can't remember a
single time I wrote a cast that turned out to be anything but a NOP (with
the possible exception of the occasional implicit memcpy).

And thus, the notation for what "most participants understand" to be C-style
casts are in fact the same notation used for several other C++ features,
including instantiation, operator invocation and so on.

2. How you believe a C-style cast, as defined by you in item 1,
behaves or should behave.

Uh... I think I just answered that.

3. Your criterion for when behavior in one case is sufficiently
similar to that in antother case, so that you can say that something
"behaves the same way" in both cases.

And that.

That's exactly why I would like you to formally establish a point of
reference, since yours appears to be quite unorthodox, to the point
where fundamental term definitions implicitly understood by most
participants can no longer be relied upon in the discussion.

Well, I hate formalities and I don't at all mind being "unorthodox" but I
still think I established that point of reference a couple of paragraphs
ago.

Thus I
would like them to be explicitly stated up front, then we can continue
discussion within your set of axioms.

Excellent. That would be a change for the better and I'm really looking
forward to that. Thank you !
 
S

Sigurd Stenersen

Igor said:
Sigurd Stenersen said:
Igor said:
Carl Daniel [VC++ MVP] wrote:
For example, if you wanted to cast from base to derived but
prevent any change in value representation (this-pointer
adjustments), you'd have to use a reinterpret_cast, because in
that context a C-style cast will behave as a static_cast.

Yeah. And now you're talking about something that's just not
possible to do with a C-style cast.

Is too:

class B {};
class D : public B {};

B* pB = new D();

D* pD1 = (D*)pB; // equivalent to static_cast

D* pD2 = (D*)(void*)pB; // equivalent to reinterpret_cast

Yeah. And now you're talking about something that's just not
possible to do with a single C-style cast.

How is this observation related to the issue of whether C-style cast
behaves "the same way" or not?

Isn't that pretty clear ? You're using an example that doesn't illustrate
*anything* but the fact that in order to achieve a certain C++ cast using
C-style casts you have to use *two* of them.

I fail to see your point. Can you
please elaborate

I already did. Repeatedly.

(preferably after you answer my other post about
establishing the terminology)?

I already did.
 
I

Igor Tandetnik

Sigurd Stenersen said:
No, you're reading a bit too much into what I'm saying. I also think
you should be careful with your assumptions about what "most
participants understand" - you may be right, but you can't *know*
this...

Well, all three of them that are still active in the thread (me, Carl
Daniel and Tom Widmer) referred you to 5.4 at one point or another,
rather emphatically. By the preponderance of evidence, I conclude that
these three believe 5.4 to be an appropriate definition of C-style cast.
In my little brain, C++ is most of what C had and some rather nifty
additions. One of the nifty little additions is the various kinds of
C++ style casts. And as C++ has it's own kind of casts, you could
safely assume that the old-fashioned C-style casts behave pretty much
exactly the same way as they do in C (even tho they may be a bit
stricter, they still *function* the same way).

So it appears that your definition of C-style cast in C++ is as follows:
C-style cast is an expression as defined in C++ standard 5.4, but only
when it is also a valid C expression (e.g. as defined in C99 standard
6.5.4). You then proceed to argue that, under this definition, C-style
cast in C++ always behaves "the same way" - namely, the way it behaves
in C. In other words, you seem to argue that C-style cast syntax in C++
is compatible with that of C: whenever you have a program that is both a
valid C and C++ program, any cast in it behaves in the same way whether
compiled by a C or C++ compiler.

Yes, I believe this to be true. There's nothing here to argue about,
really. Like I said, the whole argument stemmed from the fact that your
implied definitions of terms were different from those of other
participants.

So the conclusion appears to be as follows: C-style cast as defined in
5.4 (full definition) can exhibit a complex behavior that depends on the
types participating in the expression. However, if one limits the
discussion only to simpler cases - those that can appear in a C
program - then the behavior of the C-style cast is simple, intuitive and
consistent (it's still not a "always no-op", see below). Specifically,
the behavior matches that defined in C standard.

Would you agree or disagree with this conclusion?

By the way, under your definition the original poster was not, strictly
speaking, performing a C-style cast (since his or her expression
involved a non-POD structs and references, neither of which can appear
in a valid C program).
Now, it's been a while since I wrote anything in C, but I can't
remember a single time I wrote a cast that turned out to be anything
but a NOP (with the possible exception of the occasional implicit
memcpy).

When casting from a signed type to a larger signed type, the cast may
need to perform sign expansion. When casting between integral and
floating point types, the cast needs to perform non-trivial mathematical
operations.
Well, I hate formalities and I don't at all mind being "unorthodox"

Well, I see a little problem with that. C++ is a complex language, its
definition involves extensive terminology. Then there's a larger problem
area of programming and computer science in general, requiring still
more terminology. It would be tiresome and impractical to start every
discussion with establishing common agreed-upon definitions of the
terms.

Thus, people come to rely on implicit understanding of the accepted
terminology, as established by standards, trade literature and/or
consensus achieved in prior public discussions. Familiarity with this
accepted terminology is necessary to fully participate in the community.
This is what I meant by being "orthodox" - adhere to established
conventions whenever possible, clarify your position explicitly whenever
you don't.

If by being "unorthodox" you mean using terms in a discussion under your
own unconventional definitions, without making other participants aware
of them, then you simply won't be understood, and ultimately will be
ignored. I don't think you would consider this an attractive option.
--
With best wishes,
Igor Tandetnik

"On two occasions, I have been asked [by members of Parliament], 'Pray,
Mr. Babbage, if you put into the machine wrong figures, will the right
answers come out?' I am not able to rightly apprehend the kind of
confusion of ideas that could provoke such a question." -- Charles
Babbage
 
S

Sigurd Stenersen

Igor Tandetnik wrote a lot of schtuff

I'll give you the last word here, Igor, as I'm not operating at the same
level of abstraction (or political or pedantic correctness or whatever the
hey it is) as you are, and I can't comfortably move around up there (it
would take me forever if I tried, and that would contradict the way I've
been successfully producing excellent results over the past seventeen years
in the software industry).

If that means that you're right and I'm wrong, then you're right and I'm
wrong.
 
C

Carl Daniel [VC++ MVP]

Sigurd said:
Carl Daniel [VC++ MVP] wrote:
That depends on how you interpret "does the same thing". Sometimes a
C-style cast will result in a change of value representation (e.g.
cast from base to derived)

No, that's when you're instantiating rather than casting.

Wrong. Igor's already provided an example.

-cd
 
T

Tom Widmer

Yes, that is my perception too.



You have to take it a bit further.

Most C++ developers would agree that
(T) ce
means exactly the same as
T(ce)
and most of them would also label both as C-style casts.

I can agree to disagree, but I, and I think most others, actually
consider a C-style cast to be a syntatic rather than semantic feature,
and to look like your former case above. The fact that the latter can
perform all the same conversions as the former may even come as a
surprise to some, since I think (hope?) most people only ever use the
latter as an alternative syntax for a static_cast, not as an
alternative syntax for, e.g., reinterpret_cast.

Tom
 
I

Igor Tandetnik

Tom Widmer said:
The fact that the latter can
perform all the same conversions as the former may even come as a
surprise to some

It should not, really. C++ standard 5.2.3/1:

A simple-type-specifier (7.1.5) followed by a parenthesized
expression-list constructs a value of the specified type given the
expression list. If the expression list is a single expression, the type
conversion expression is equivalent (in definedness, and if defined in
meaning) to the corresponding cast expression (5.4).

--
With best wishes,
Igor Tandetnik

"On two occasions, I have been asked [by members of Parliament], 'Pray,
Mr. Babbage, if you put into the machine wrong figures, will the right
answers come out?' I am not able to rightly apprehend the kind of
confusion of ideas that could provoke such a question." -- Charles
Babbage
 
T

Tom Widmer

It should not, really. C++ standard 5.2.3/1:

A simple-type-specifier (7.1.5) followed by a parenthesized
expression-list constructs a value of the specified type given the
expression list. If the expression list is a single expression, the type
conversion expression is equivalent (in definedness, and if defined in
meaning) to the corresponding cast expression (5.4).

Indeed, but given that most people regularly make use of "explicit
type conversion (functional notation)", the fact that it might
actually be performing a reinterpret_cast or a const_cast is a bit
alarming IMHO. I've never used it for anything other than a
static_cast, so it's a shame that the standard doesn't enforce this.

Tom
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top