By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,423 Members | 1,294 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,423 IT Pros & Developers. It's quick & easy.

casting A* to A& ?

P: n/a
What happens exactly when I do the following:

struct A {
int i;
string j;
A() {}
};

void f(A& a) {
cout << a.i << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
A a;
a.i = 6;
A* pa = &a;
f((A&)pa); // CRITICAL POINT
f(*pa); // works as expected
return 0;
}
How come that this is legal, anyway?
Lately I've seen some people expect that (A&)pa be equivalent to *pa, which
is not according to the example above. (The output for f((A&)pa) looks like
some integer, but surely not 6 as should be if it meant f(*pa).)
Nov 17 '05 #1
Share this Question
Share on Google+
44 Replies


P: n/a
Agoston Bejo wrote:
What happens exactly when I do the following:

struct A {
int i;
string j;
A() {}
};

void f(A& a) {
cout << a.i << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
A a;
a.i = 6;
A* pa = &a;
f((A&)pa); // CRITICAL POINT
f(*pa); // works as expected
return 0;
}
How come that this is legal, anyway?
You can cast something at an address to something else at the same address.
Try doing the same cast with a constant and you'll see that that is not
allowed.

Lately I've seen some people expect that (A&)pa be equivalent to *pa,
which is not according to the example above.
No, it is not. *pa is a reference to whatever pa is pointing to, tho. So
f(*pa);
is perfectly fine.

(The output for
f((A&)pa) looks like some integer, but surely not 6 as should be if
it meant f(*pa).)


The integer is equal to the address of a.

What actually happens is you're telling the compiler that "look here, pa is
not a pointer it's a struct of type A". That is in fact wrong, but because
you're telling the compiler that you know better it let's you do it. And
you're lucky, because the size of pa happens to be the same as the size of
an A instance. As it happens, the value of p overlaps A::i when you do the
cast.

Thus, you only get bogus results in this simple example, in reality you'd
usually get an access violation or some other hardtofind bug.
In other words, when you use a typecast, you're telling the compiler that
you know what you're doing. And that's a very silly thing to tell the
compiler if you don't know what you're doing...
(Yes, references are implemented the same way as pointers. But they have
different semantics.)
--
Sigurd
http://utvikling.com
Nov 17 '05 #2

P: n/a
Thanks for the thorough answer!
"Sigurd Stenersen" <si*****@utvikling.com> wrote in message
news:%2******************@TK2MSFTNGP15.phx.gbl...

[...]
What actually happens is you're telling the compiler that "look here, pa is not a pointer it's a struct of type A". That is in fact wrong, but because you're telling the compiler that you know better it let's you do it. And
So does (Type)var mean the same as reinterpret_cast<Type>(var)?
I thought it meant static_cast<Type>(var).
Or is it context-dependent, how C-style casts are interpreted?
you're lucky, because the size of pa happens to be the same as the size of
an A instance. As it happens, the value of p overlaps A::i when you do the cast.


I think the first statement (about the sizes) is not really relevant, what
matters is that the size of an A instance is at least as big as the size of
pa, so no out-of-heap memory is read which could cause access violation. Am
I right?

However, I've tried it with A having only a char member and nothing else,
but no access violation occured in this case, either. (I compiled the
example both in debug and release mode.)
I think it should have produced some runtime error, especially in debug
mode, shouldn't it?


Nov 17 '05 #3

P: n/a
Hello,
What happens exactly when I do the following:

struct A {
int i;
string j;
A() {}
};

void f(A& a) {
cout << a.i << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
A a;
a.i = 6;
A* pa = &a;
f((A&)pa); // CRITICAL POINT
f(*pa); // works as expected
return 0;
}
How come that this is legal, anyway?
Lately I've seen some people expect that (A&)pa be equivalent to *pa, which is not according to the example above. (The output for f((A&)pa) looks like some integer, but surely not 6 as should be if it meant f(*pa).)


If you would used C++ style cast notation.
The only valid code would be: f(reinterpret_cast<A&>(pa)); // A* & -> A &.

When you see *_cast operators in code, this often means that program could
be written better. But when you see reinterpret_cast, this usually means
that something is wrong, unless it's low level code.
--
Vladimir Nesterovsky
e-mail: vl******@nesterovsky-bros.com
home: http://www.nesterovsky-bros.com
Nov 17 '05 #4

P: n/a
Agoston Bejo wrote:
"Sigurd Stenersen" <si*****@utvikling.com> wrote in message
news:%2******************@TK2MSFTNGP15.phx.gbl...

[...]
What actually happens is you're telling the compiler that "look
here, pa is not a pointer it's a struct of type A". That is in fact
wrong, but because you're telling the compiler that you know better
it let's you do it. And
So does (Type)var mean the same as reinterpret_cast<Type>(var)?


I *think* so. I don't use that sort of cast myself.

Or is it context-dependent, how C-style casts are interpreted?
No.

you're lucky, because the size of pa happens to be the same as the
size of an A instance. As it happens, the value of p overlaps A::i
when you do the cast.


I think the first statement (about the sizes) is not really relevant,


Oh, yes, it is *highly* relevant.

Consider this :

struct A
{
// char s[100000];
int i;
};

void f(A& a)
{
cout << a.i << endl;
}

void main()
{
A *pa = new A;
f((A&) pa);
}

That will be bogus but still "work". Now, remove the // from the third line
and guess what happens ?

Also, consider your original code and just change the cout statement to
cout << a.i << a.j.c_str() << endl;
and you achieve pretty much the same result...

what matters is that the size of an A instance is at least as big as
the size of pa, so no out-of-heap memory is read which could cause
access violation. Am I right?
No, it's the other way around. As long as the variable that's actually used
(pa) is big enough, at least you wont corrupt other variables. Still, the
results will be bogus at best.

However, I've tried it with A having only a char member and nothing
else, but no access violation occured in this case, either. (I
compiled the example both in debug and release mode.)
I think it should have produced some runtime error, especially in
debug mode, shouldn't it?


No, it's *legal*. You told the compiler you knew what you were doing...
--
Sigurd
http://utvikling.com
Nov 17 '05 #5

P: n/a
On Fri, 8 Oct 2004 14:27:40 +0200, "Agoston Bejo" <gu***@freemail.hu>
wrote:
Thanks for the thorough answer!
"Sigurd Stenersen" <si*****@utvikling.com> wrote in message
news:%2******************@TK2MSFTNGP15.phx.gbl. ..

[...]
What actually happens is you're telling the compiler that "look here, pais
not a pointer it's a struct of type A". That is in fact wrong, but

because
you're telling the compiler that you know better it let's you do it. And


So does (Type)var mean the same as reinterpret_cast<Type>(var)?
I thought it meant static_cast<Type>(var).
Or is it context-dependent, how C-style casts are interpreted?


It is context dependent. A C-style cast can act as a static_cast, a
const_cast or a reinterpret_cast, as well as combinations of those. It
can also perform casts that can't even be done by reinterpret_cast,
such as casting to a private base class.
you're lucky, because the size of pa happens to be the same as the size of
an A instance. As it happens, the value of p overlaps A::i when you do

the
cast.


I think the first statement (about the sizes) is not really relevant, what
matters is that the size of an A instance is at least as big as the size of
pa, so no out-of-heap memory is read which could cause access violation. Am
I right?


The important thing is that your function f only accesses the first 4
bytes of the passed object, so it only accesses the 4 bytes of the
passed pointer value, giving out a garbage int value that is the value
of the passed pointer.

However, the code has undefined behaviour.
However, I've tried it with A having only a char member and nothing else,
but no access violation occured in this case, either. (I compiled the
example both in debug and release mode.)
Try instead changing your function to print out a.j rather than a.i.
That will likely cause a proper crash, since it will treat the bytes
of stack space after the passed pointer as a valid string object, when
in reality they probably contain random byte values.
I think it should have produced some runtime error, especially in debug
mode, shouldn't it?


Undefined behaviour often doesn't produce any obvious results, rather
it corrupts the heap or stack, causing your program to produce
incorrect results or crash further down the line. It you're very lucky
it crashes at the point of the error, but this is quite rare.

Tom
Nov 17 '05 #6

P: n/a
C-style cast are interpreted either as static_cast (if a standard conversion
exists), or reinterpret_cast otherwise.

"Sigurd Stenersen" <si*****@utvikling.com> wrote in message
news:OQ**************@TK2MSFTNGP12.phx.gbl...

So does (Type)var mean the same as reinterpret_cast<Type>(var)?


I *think* so. I don't use that sort of cast myself.

Or is it context-dependent, how C-style casts are interpreted?


No.

you're lucky, because the size of pa happens to be the same as the
size of an A instance. As it happens, the value of p overlaps A::i
when you do the cast.


I think the first statement (about the sizes) is not really relevant,


Oh, yes, it is *highly* relevant.

Consider this :

struct A
{
// char s[100000];
int i;
};

void f(A& a)
{
cout << a.i << endl;
}

void main()
{
A *pa = new A;
f((A&) pa);
}

That will be bogus but still "work". Now, remove the // from the third
line
and guess what happens ?

Also, consider your original code and just change the cout statement to
cout << a.i << a.j.c_str() << endl;
and you achieve pretty much the same result...

what matters is that the size of an A instance is at least as big as
the size of pa, so no out-of-heap memory is read which could cause
access violation. Am I right?


No, it's the other way around. As long as the variable that's actually
used
(pa) is big enough, at least you wont corrupt other variables. Still, the
results will be bogus at best.

However, I've tried it with A having only a char member and nothing
else, but no access violation occured in this case, either. (I
compiled the example both in debug and release mode.)
I think it should have produced some runtime error, especially in
debug mode, shouldn't it?


No, it's *legal*. You told the compiler you knew what you were doing...
--
Sigurd
http://utvikling.com

Nov 17 '05 #7

P: n/a
Tom Widmer wrote:
On Fri, 8 Oct 2004 14:27:40 +0200, "Agoston Bejo" <gu***@freemail.hu>
wrote:
Thanks for the thorough answer!

"Sigurd Stenersen" <si*****@utvikling.com> wrote in message
news:%2******************@TK2MSFTNGP15.phx.gbl...

[...]
What actually happens is you're telling the compiler that "look
here, pa is not a pointer it's a struct of type A". That is in
fact wrong, but because you're telling the compiler that you know
better it let's you do it. And


So does (Type)var mean the same as reinterpret_cast<Type>(var)?
I thought it meant static_cast<Type>(var).
Or is it context-dependent, how C-style casts are interpreted?


It is context dependent. A C-style cast can act as a static_cast, a
const_cast or a reinterpret_cast, as well as combinations of those. It
can also perform casts that can't even be done by reinterpret_cast,
such as casting to a private base class.


It does the same thing no matter what the context is - it treats something
of one type like it actually is some other type.

Casting to certain types results in the creation of a temporary object of
the destination type. However, that's not related to context but rather
it's related to the destination type.
--
Sigurd
http://utvikling.com
Nov 17 '05 #8

P: n/a
Alexander Grigoriev wrote:
"Sigurd Stenersen" <si*****@utvikling.com> wrote in message
Or is it context-dependent, how C-style casts are interpreted?


No.

C-style cast are interpreted either as static_cast (if a standard
conversion exists), or reinterpret_cast otherwise.


So ? C-style casts work the same way in any context. You could argue that
there is one exception (I mentioned this in my last post), but that's
depending on the target type rather than on the context and it's not really
a cast anyway. It just looks like one.
--
Sigurd
http://utvikling.com
Nov 17 '05 #9

P: n/a
Sigurd Stenersen wrote:
Tom Widmer wrote:
It is context dependent. A C-style cast can act as a static_cast, a
const_cast or a reinterpret_cast, as well as combinations of those.
It can also perform casts that can't even be done by
reinterpret_cast,
such as casting to a private base class.


It does the same thing no matter what the context is - it treats
something of one type like it actually is some other type.


Tom is correct. According to 5.4/5 and 5.4/7 of the C++ Standard:

5 The conversions performed by
- a const_cast (5.2.11),
- a static_cast (5.2.9),
- a static_cast followed by a const_cast,
- a reinterpret_cast (5.2.10), or
- a reinterpret_cast followed by a const_cast,
can be performed using the cast notation of explicit type conversion. The
same semantic restrictions and behaviors apply. If a conversion can be
interpreted in more than one of the ways listed above, the interpretation
that appears first in the list is used, even if a cast resulting from that
interpretation is illformed. If a conversion can be interpreted in more than
one way as a static_cast followed by a const_cast, the conversion is
illformed.

[Example:

struct A {};
struct I1 : A {};
struct I2 : A {};
struct D : I1, I2 {};
A *foo( D *p ) {
return (A*)( p ); // illformed static_cast interpretation
}

-end example]

7 In addition to those conversions, the following static_cast and
reinterpret_cast operations (optionally followed by a const_cast operation)
may be performed using the cast notation or explicit type conversion, even
if the base class type is not accessible:
- a pointer to an object of derived class type or an lvalue of derived class
type may be explicitly converted to a pointer or reference to an unambiguous
base class type, respectively;
- a pointer to member of derived class type may be explicitly converted to a
pointer to member of an unambiguous nonvirtual base class type;
- a pointer to an object of nonvirtual base class type, an lvalue of
nonvirtual base class type, or a pointer to member of nonvirtual base class
type may be explicitly converted to a pointer, a reference, or a pointer to
member of a derived class type, respectively.
-cd
Nov 17 '05 #10

P: n/a
"Sigurd Stenersen" <si*****@utvikling.com> wrote in message news:%2****************@TK2MSFTNGP15.phx.gbl...
Alexander Grigoriev wrote:
"Sigurd Stenersen" <si*****@utvikling.com> wrote in message
Or is it context-dependent, how C-style casts are interpreted?

No.
C-style cast are interpreted either as static_cast (if a standard
conversion exists), or reinterpret_cast otherwise.


So ? C-style casts work the same way in any context. You could argue that
there is one exception (I mentioned this in my last post), but that's
depending on the target type rather than on the context and it's not really
a cast anyway. It just looks like one.


You've made a distinction I cannot follow, and I believe
it is incorrect as well. The 'target type' certainly must be
considered part of the context of an expression forming
the right-hand side of an assignment.

The very reason that the old C casts should be avoided
is because they can do different things depending on
context. For example, consider this cast:
x_ptr = (SomeType *)p;
Is is a static_cast or a reinterpret_cast? You cannot
tell until we know the types of both x_ptr and p.
Given these declarations:
class Base {} *p;
class Derv : public Base {} *x_ptr;
then it was a static_cast.
Given these declarations:
class Apple {} *p;
class Orange {} *x_ptr;
then it was a reinterpret_cast.

What makes the C cast so insidious is that its operation
can change as a side effect of changes in code far
removed from the location of the cast. If not for that
misfeature, (if they were as stable as you claim), they
would be safer to use. A static_cast would always
remain a converstion between compatible types,
(and a reinterpret_cast would remain as dangerous
as ever).
Sigurd
http://utvikling.com


--
--Larry Brasfield
email: do***********************@hotmail.com
Above views may belong only to me.
Nov 17 '05 #11

P: n/a
Carl Daniel [VC++ MVP] wrote:
Sigurd Stenersen wrote:
Tom Widmer wrote:
It is context dependent. A C-style cast can act as a static_cast, a
const_cast or a reinterpret_cast, as well as combinations of those.
It can also perform casts that can't even be done by
reinterpret_cast,
such as casting to a private base class.


It does the same thing no matter what the context is - it treats
something of one type like it actually is some other type.


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. The fact that you have three different
ways to do a C++ style cast, with different restrictions for each one, does
not change the way the C-style cast works...
--
Sigurd
http://utvikling.com
Nov 17 '05 #12

P: n/a
Larry Brasfield wrote:
"Sigurd Stenersen" <si*****@utvikling.com> wrote in message
news:%2****************@TK2MSFTNGP15.phx.gbl...
Alexander Grigoriev wrote:
"Sigurd Stenersen" <si*****@utvikling.com> wrote in message
> Or is it context-dependent, how C-style casts are interpreted?

No.

C-style cast are interpreted either as static_cast (if a standard
conversion exists), or reinterpret_cast otherwise.
So ? C-style casts work the same way in any context. You could
argue that there is one exception (I mentioned this in my last
post), but that's depending on the target type rather than on the
context and it's not really a cast anyway. It just looks like one.


You've made a distinction I cannot follow, and I believe
it is incorrect as well.


It's not *that* hard... Given
char *p = "...";
(std::string) p;
you're doing something more than just changing the "compiler perceived"
type. My point is that this is not really a cast, it's an instantiation
exactly the same way that
char *p = "...";
std::string(p);
is an instantiation and not a cast.

The case is not the same for actual typecasts that use the same notation,
e.g.
int i;
(char) i;
is the same as
int i;
char(i);
which is a cast and not an instantiation.

The 'target type' certainly must be
considered part of the context of an expression forming
the right-hand side of an assignment.


In that case we have different ideas about the meaning of the word
"context". I guess I could be wrong, english is not my native language.
--
Sigurd
http://utvikling.com
Nov 17 '05 #13

P: n/a
On Fri, 8 Oct 2004 16:20:27 +0200, "Sigurd Stenersen"
<si*****@utvikling.com> wrote:
Tom Widmer wrote:
On Fri, 8 Oct 2004 14:27:40 +0200, "Agoston Bejo" <gu***@freemail.hu>
wrote:
Thanks for the thorough answer!

"Sigurd Stenersen" <si*****@utvikling.com> wrote in message
news:%2******************@TK2MSFTNGP15.phx.gbl...

[...]

What actually happens is you're telling the compiler that "look
here, pa is not a pointer it's a struct of type A". That is in
fact wrong, but because you're telling the compiler that you know
better it let's you do it. And

So does (Type)var mean the same as reinterpret_cast<Type>(var)?
I thought it meant static_cast<Type>(var).
Or is it context-dependent, how C-style casts are interpreted?
It is context dependent. A C-style cast can act as a static_cast, a
const_cast or a reinterpret_cast, as well as combinations of those. It
can also perform casts that can't even be done by reinterpret_cast,
such as casting to a private base class.


It does the same thing no matter what the context is - it treats something
of one type like it actually is some other type.


By context I mean the combination of source type and destination type.
Without knowing both of those types, you can't tell what conversion is
going to be performed.

Depending on the relationship, the cast might cause a function to be
called, might need a cast pointer value to be adjusted (multiple
inheritence), 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.
Casting to certain types results in the creation of a temporary object of
the destination type.
All casts to non-reference types give you a temporary (or rvalue),
unless I'm mistaken.
However, that's not related to context but rather
it's related to the destination type.


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

Tom
Nov 17 '05 #14

P: n/a
"Sigurd Stenersen" <si*****@utvikling.com> wrote in message
news:ue**************@TK2MSFTNGP15.phx.gbl
Tom Widmer wrote:
It is context dependent. A C-style cast can act as a static_cast, a
const_cast or a reinterpret_cast, as well as combinations of those.
It can also perform casts that can't even be done by
reinterpret_cast, such as casting to a private base class.


It does the same thing no matter what the context is - it treats
something of one type like it actually is some other type.


You seem to argue that a C-style cast is always the same as
reinterpret_cast - that is, it just takes bits in memory, and interprets
these bits as a representation of a different type. This is not always
so. Consider:

class A {int a;};
class B {int b;};

class C : public A, public B {};

C c;
C* pC = &c;

B* pB1 = static_cast<B*>(pC);

Here, the physical value of pB1 is very likely different from that of pC
(that is, (void*)pB1 != (void*)pC ), because B subobject is at a
non-zero offset inside C (a zero offset is most likely occupied by A
subobject).

B* pB2 = reinterpret_cast<B*>(pC);

Here, the physical value of pB2 is the same as pC (that's the whole
point of reinterpret_cast). Incidentally, pB2 does not point to a valid
object of type B. Dereferencing it would cause undefined behavior.

B* pB3 = (B*)pC;

Here, the C-style cast behaves the same way as static_cast, not as
reinterpret_cast. pB3 == pB1 and is different from pC.

class D {};
D* pD = (D*)pC;

Here, C-style cast behaves like reinterpret_cast - the physical value of
pD is the same as pC.

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.
--
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
Nov 17 '05 #15

P: n/a
On Fri, 8 Oct 2004 15:32:29 +0200, "Sigurd Stenersen"
<si*****@utvikling.com> wrote:
However, I've tried it with A having only a char member and nothing
else, but no access violation occured in this case, either. (I
compiled the example both in debug and release mode.)
I think it should have produced some runtime error, especially in
debug mode, shouldn't it?


No, it's *legal*. You told the compiler you knew what you were doing...


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

Tom
Nov 17 '05 #16

P: n/a
"Agoston Bejo" <gu***@freemail.hu> wrote in message
news:eY***************@TK2MSFTNGP09.phx.gbl
int _tmain(int argc, _TCHAR* argv[])
{
A a;
a.i = 6;
A* pa = &a;
f((A&)pa); // CRITICAL POINT


This is undefined behavior, so there are no rules on how the compiler
should interpret it. I believe VC++ would treat it the same way as

f( *(A*)&pa );

That is, the memory occupied by pa pointer is treated as if it held A
object. Inside f, a.i would likely be equal to (int)pa
--
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
Nov 17 '05 #17

P: n/a
Sigurd Stenersen wrote:
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.


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) and sometimes it wont.

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.

Contrast this to C where casts between any two pointer types are the
equivalent of a reinterpret_cast.

-cd
Nov 17 '05 #18

P: n/a
On Fri, 8 Oct 2004 17:12:18 +0200, "Sigurd Stenersen"
<si*****@utvikling.com> wrote:
Carl Daniel [VC++ MVP] wrote:
Sigurd Stenersen wrote:
Tom Widmer wrote:
It is context dependent. A C-style cast can act as a static_cast, a
const_cast or a reinterpret_cast, as well as combinations of those.
It can also perform casts that can't even be done by
reinterpret_cast,
such as casting to a private base class.

It does the same thing no matter what the context is - it treats
something of one type like it actually is some other type.


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!

Tom
Nov 17 '05 #19

P: n/a
Carl Daniel [VC++ MVP] wrote:
Sigurd Stenersen wrote:
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.


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.

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.

Contrast this to C where casts between any two pointer types are the
equivalent of a reinterpret_cast.


Yes, that is one of the differences between C-style and C++ style casts.
--
Sigurd
http://utvikling.com
Nov 17 '05 #20

P: n/a
Tom Widmer wrote:
On Fri, 8 Oct 2004 16:20:27 +0200, "Sigurd Stenersen"
<si*****@utvikling.com> wrote:
Tom Widmer wrote:
It is context dependent. A C-style cast can act as a static_cast, a
const_cast or a reinterpret_cast, as well as combinations of those.
It can also perform casts that can't even be done by
reinterpret_cast, such as casting to a private base class.
It does the same thing no matter what the context is - it treats
something of one type like it actually is some other type.


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...

Casting to certain types results in the creation of a temporary
object of the destination type.


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.

However, that's not related to context but rather
it's related to the destination type.


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.
--
Sigurd
http://utvikling.com
Nov 17 '05 #21

P: n/a
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"...
--
Sigurd
http://utvikling.com
Nov 17 '05 #22

P: n/a
Tom Widmer wrote:
On Fri, 8 Oct 2004 15:32:29 +0200, "Sigurd Stenersen"
<si*****@utvikling.com> wrote:
However, I've tried it with A having only a char member and nothing
else, but no access violation occured in this case, either. (I
compiled the example both in debug and release mode.)
I think it should have produced some runtime error, especially in
debug mode, shouldn't it?


No, it's *legal*. You told the compiler you knew what you were
doing...


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)
--
Sigurd
http://utvikling.com
Nov 17 '05 #23

P: n/a
Tom Widmer wrote:
On Fri, 8 Oct 2004 17:12:18 +0200, "Sigurd Stenersen"
<si*****@utvikling.com> wrote:
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.
--
Sigurd
http://utvikling.com
Nov 17 '05 #24

P: n/a
"Sigurd Stenersen" <si*****@utvikling.com> wrote in message
news:uB**************@TK2MSFTNGP15.phx.gbl
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

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
Nov 17 '05 #25

P: n/a
On Fri, 8 Oct 2004 18:24:10 +0200, "Sigurd Stenersen"
<si*****@utvikling.com> wrote:
Tom Widmer wrote:
On Fri, 8 Oct 2004 17:12:18 +0200, "Sigurd Stenersen"
<si*****@utvikling.com> wrote:
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
Nov 17 '05 #26

P: n/a
"Sigurd Stenersen" <si*****@utvikling.com> wrote in message
news:ux**************@TK2MSFTNGP11.phx.gbl
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
Nov 17 '05 #27

P: n/a
Igor Tandetnik wrote:
"Sigurd Stenersen" <si*****@utvikling.com> wrote in message
news:uB**************@TK2MSFTNGP15.phx.gbl
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.
--
Sigurd
http://utvikling.com
Nov 17 '05 #28

P: n/a
Tom Widmer wrote:
On Fri, 8 Oct 2004 18:24:10 +0200, "Sigurd Stenersen"
<si*****@utvikling.com> wrote:
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.


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.
--
Sigurd
http://utvikling.com
Nov 17 '05 #29

P: n/a
"Sigurd Stenersen" <si*****@utvikling.com> wrote in message
news:%2****************@TK2MSFTNGP11.phx.gbl
Igor Tandetnik wrote:
"Sigurd Stenersen" <si*****@utvikling.com> wrote in message
news:uB**************@TK2MSFTNGP15.phx.gbl
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
Nov 17 '05 #30

P: n/a
Igor Tandetnik wrote:
"Sigurd Stenersen" <si*****@utvikling.com> wrote in message
news:ux**************@TK2MSFTNGP11.phx.gbl
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.

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.


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 !

--
Sigurd
http://utvikling.com
Nov 17 '05 #31

P: n/a
Igor Tandetnik wrote:
"Sigurd Stenersen" <si*****@utvikling.com> wrote in message
news:%2****************@TK2MSFTNGP11.phx.gbl
Igor Tandetnik wrote:
"Sigurd Stenersen" <si*****@utvikling.com> wrote in message
news:uB**************@TK2MSFTNGP15.phx.gbl
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.
--
Sigurd
http://utvikling.com
Nov 17 '05 #32

P: n/a
"Sigurd Stenersen" <si*****@utvikling.com> wrote in message
news:u$*************@TK2MSFTNGP14.phx.gbl
Igor Tandetnik wrote:
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...


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
Nov 17 '05 #33

P: n/a
"Sigurd Stenersen" <si*****@utvikling.com> wrote in message
news:Of**************@TK2MSFTNGP12.phx.gbl...
The case is not the same for actual typecasts that use the same notation,
e.g.
int i;
(char) i;
is the same as
int i;
char(i);
which is a cast and not an instantiation.


Hmmmmm...

float f;
(int) f;

Cast or instantiation?

--
Truth,
James Curran
Home: www.noveltheory.com Work: www.njtheater.com
Blog: www.honestillusion.com Day Job: www.partsearch.com
(note new day job!)
Nov 17 '05 #34

P: n/a
James Curran wrote:
"Sigurd Stenersen" <si*****@utvikling.com> wrote in message
news:Of**************@TK2MSFTNGP12.phx.gbl...
The case is not the same for actual typecasts that use the same
notation, e.g.
int i;
(char) i;
is the same as
int i;
char(i);
which is a cast and not an instantiation.


Hmmmmm...

float f;
(int) f;

Cast or instantiation?


That's a cast, and not a NOP.

Good point, even though it's the same in C.
--
Sigurd
http://utvikling.com
Nov 17 '05 #35

P: n/a
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.
--
Sigurd
http://utvikling.com
Nov 17 '05 #36

P: n/a
Sigurd Stenersen wrote:
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
Nov 17 '05 #37

P: n/a
On Fri, 8 Oct 2004 18:59:26 +0200, "Sigurd Stenersen"
<si*****@utvikling.com> wrote:
Tom Widmer wrote:
On Fri, 8 Oct 2004 18:24:10 +0200, "Sigurd Stenersen"
<si*****@utvikling.com> wrote:
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.


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.


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
Nov 17 '05 #38

P: n/a
"Tom Widmer" <to********@hotmail.com> wrote in message
news:38********************************@4ax.com
On Fri, 8 Oct 2004 18:59:26 +0200, "Sigurd Stenersen"
<si*****@utvikling.com> wrote:
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.


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
Nov 17 '05 #39

P: n/a
On Mon, 11 Oct 2004 09:40:11 -0400, "Igor Tandetnik"
<it********@mvps.org> wrote:
"Tom Widmer" <to********@hotmail.com> wrote in message
news:38********************************@4ax.com
On Fri, 8 Oct 2004 18:59:26 +0200, "Sigurd Stenersen"
<si*****@utvikling.com> wrote:
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.


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).


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
Nov 17 '05 #40

P: n/a
int i;
(char) i;

I am sure it is an rvalue. Just try this:
int i;
(char) i = 123; // error

However, on non-builtin types it is indeed an lvalue:
struct A { A(int) {} };

int i;
(A)i = (A)4;

The result is a temporary lvalue.

So, builtin types do not instantiate but classes do?

"Sigurd Stenersen" wrote:
Tom Widmer wrote:
On Fri, 8 Oct 2004 16:20:27 +0200, "Sigurd Stenersen"
<si*****@utvikling.com> wrote:
Tom Widmer wrote:
It is context dependent. A C-style cast can act as a static_cast, a
const_cast or a reinterpret_cast, as well as combinations of those.
It can also perform casts that can't even be done by
reinterpret_cast, such as casting to a private base class.

It does the same thing no matter what the context is - it treats
something of one type like it actually is some other type.


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...

Casting to certain types results in the creation of a temporary
object of the destination type.


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.

However, that's not related to context but rather
it's related to the destination type.


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.
--
Sigurd
http://utvikling.com

Nov 17 '05 #41

P: n/a
Pieter de Goeje <Pieter de Go***@discussions.microsoft.com> wrote:
int i;
(char) i;

I am sure it is an rvalue. Just try this:
int i;
(char) i = 123; // error

However, on non-builtin types it is indeed an lvalue:
struct A { A(int) {} };

int i;
(A)i = (A)4;

The result is a temporary lvalue.
No. Temporary objects are rvalues. I don't know if it's possible to define
the terms lvalue and rvalue WRT C++ except to list those things the standard
says they are; a more abstract definition eludes me. I once posted this as
an example of a sort of built-in joke:

*****

http://groups.google.com/groups?selm...m7p6%404ax.com

struct X
{
};

void g(X&);

void f()
{
X() = X();

g(X() = X());

g(X()); // No good
}

Note that above, the result of assigning one rvalue to another rvalue
is a modifiable lvalue. :)

*****

The difference between the rvalues produced by X() and int() is that the
former has member functions you can call on it, and you're allowed to call
them, including the assignment operator.
So, builtin types do not instantiate but classes do?


I don't get the question.

--
Doug Harrison
Microsoft MVP - Visual C++
Nov 17 '05 #42

P: n/a
"Doug Harrison [MVP]" <ds*@mvps.org> wrote in message
news:pj********************************@4ax.com
So, builtin types do not instantiate but classes do?


I don't get the question.


It's a reference to Sigurd Stenersen's insistence that some instances of
C-style cast expression are "real" casts, and others are kinda sorta not
really casts but, you know, "instantiations" - a position that got
everyone baffled for a while. You'll have to read the whole thread to
understand this fine point. It's not really all that interesting.
--
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
Nov 17 '05 #43

P: n/a
Pieter de Goeje wrote:
I am sure it is an rvalue. Just try this:
int i;
(char) i = 123; // error
Yes. So this is obviously a cast and not an instantiation.

However, on non-builtin types it is indeed an lvalue:
struct A { A(int) {} };

int i;
(A)i = (A)4;

The result is a temporary lvalue.


Yes. And here you're not casting, you're instantiating. Twice.
--
Sigurd
http://utvikling.com
Nov 17 '05 #44

P: n/a
Igor Tandetnik wrote:
"Doug Harrison [MVP]" <ds*@mvps.org> wrote in message
news:pj********************************@4ax.com
So, builtin types do not instantiate but classes do?
I don't get the question.


It's a reference to Sigurd Stenersen's insistence that some instances
of C-style cast expression are "real" casts, and others are kinda
sorta not really casts but, you know, "instantiations"


That is almost correct. Except when you *do* instantiate you're *not using*
a "C-style cast expression". It just looks kinda similar.

a position that got everyone baffled for a while.
Whoo-hoo !

I managed to make a lot of highly skilled people stop and think for a while.
That's quite an achievement.

Thank you so much for pointing that out, you just made my day.

You'll have to read the whole
thread to understand this fine point.
That's a statement about you.

It's not really all that interesting.


That's another statement about you.
--
Sigurd
http://utvikling.com
Nov 17 '05 #45

This discussion thread is closed

Replies have been disabled for this discussion.