Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Temporary objects, l-values.

Reply
Thread Tools

Temporary objects, l-values.

 
 
jason.cipriani@gmail.com
Guest
Posts: n/a
 
      02-19-2008
First I have a question about the "official" definition of a
"temporary object".

So in this code:

void function1 (SomeThing a) { }

void function2 (void) {
SomeThing b;
function1(b);
}

A copy of b is made to pass to function1(). That's a temporary object,
of course. I was always under the impression that a "temporary object"
was an object created by the compiler implicitly, and it's entirely
"behind the scenes" (as in the above example). But, is the object
created in the following code also called a "temporary object":

void function1 (SomeThing &a) { }

void function2 (void) {
function1(SomeThing());
}

I mean, you explicitly construct it. It's not secretly created by the
compiler -- but it is anonymous (outside of function1), and it does
get destroyed after the statement is evaluated. It's just not
completely "behind the scenes". Would that also be called, officially,
a "temporary object"?

My second question is about l-values. In the following code:

struct A {
A (void) { }
};

void function (void) {
A a;
A() = a;
}

That compiles on all the compilers I've tested it on (Borland's BCC32,
GCC, and Comeau); and I expected it to. That would mean that "A()" is
not a temporary, by definition, since it is also an l-value. It seems
weird that I can say "A() = something;". I mean I know exactly what it
is doing, but it doesn't make sense to do it (just like trying to set
"2 = 3" doesn't really make much sense) (unless the = operator has
some other side effects that you want). Are the compilers I've tried
it on broken? Or is A() really an l-value there? Or is it compiler-
specific whether or not that is accepted or not? The reason I am
confused is because of code like this (untested, I'm just typing it in
this email hopefully I didn't screw up something important):

struct X {
};

struct Y {
Y (const X &) { }
};

void function (Y &) { }

void function2 (void) {
X x;
function(Y(x));
}

That code compiles with recent versions of GCC, Borland's compiler,
and the MS compiler. However, Comeau does not compile it, complaining
that non-const reference parameters to functions must be l-values. Yet
Comeau does compile the following (add a default constructor to Y in
the above example for this):

void function2 (void) {
Y y;
(Y(x)) = y;
}

Comeau's inconsistency about what it thinks an l-value is bugs me (I
asked them about this one and am waiting for a response).

So I'm a little confused. Mostly I'm asking to clear up some points in
a discussion I'm having with somebody on another newsgroup.

Thanks,
Jason
 
Reply With Quote
 
 
 
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      02-19-2008
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:

> First I have a question about the "official" definition of a
> "temporary object".
>
> So in this code:
>
> void function1 (SomeThing a) { }
>
> void function2 (void) {
> SomeThing b;
> function1(b);
> }
>
> A copy of b is made to pass to function1(). That's a temporary object,
> of course. I was always under the impression that a "temporary object"
> was an object created by the compiler implicitly, and it's entirely
> "behind the scenes" (as in the above example). But, is the object
> created in the following code also called a "temporary object":
>
> void function1 (SomeThing &a) { }
>
> void function2 (void) {
> function1(SomeThing());
> }
>
> I mean, you explicitly construct it. It's not secretly created by the
> compiler -- but it is anonymous (outside of function1), and it does
> get destroyed after the statement is evaluated. It's just not
> completely "behind the scenes". Would that also be called, officially,
> a "temporary object"?


a) Yes.

b) The code should not compile. The temporary does not bind to non-const
references. See [8.5.3/5].


> My second question is about l-values. In the following code:
>
> struct A {
> A (void) { }
> };
>
> void function (void) {
> A a;
> A() = a;
> }
>
> That compiles on all the compilers I've tested it on (Borland's BCC32,
> GCC, and Comeau); and I expected it to. That would mean that "A()" is
> not a temporary, by definition, since it is also an l-value.


Nope. You seem to think that something needs to be an l-value to allow for
assignment. That is not true for class types. For class types, the
assignment operator is a member function. You can call non-const member
functions on r-values.


> It seems
> weird that I can say "A() = something;". I mean I know exactly what it
> is doing, but it doesn't make sense to do it (just like trying to set
> "2 = 3" doesn't really make much sense) (unless the = operator has
> some other side effects that you want).


Huh? The reason that 2 = 3 does not make sense is that 2 is const. A() is
not const. Why should it not make sense to set its value?

> Are the compilers I've tried
> it on broken? Or is A() really an l-value there? Or is it compiler-
> specific whether or not that is accepted or not? The reason I am
> confused is because of code like this (untested, I'm just typing it in
> this email hopefully I didn't screw up something important):
>
> struct X {
> };
>
> struct Y {
> Y (const X &) { }
> };
>
> void function (Y &) { }
>
> void function2 (void) {
> X x;
> function(Y(x));
> }
>
> That code compiles with recent versions of GCC, Borland's compiler,
> and the MS compiler. However, Comeau does not compile it, complaining
> that non-const reference parameters to functions must be l-values.


a) gcc also does not compile the code.
b) Comeau is correct.

> Yet
> Comeau does compile the following (add a default constructor to Y in
> the above example for this):
>
> void function2 (void) {
> Y y;
> (Y(x)) = y;
> }
>
> Comeau's inconsistency about what it thinks an l-value is bugs me (I
> asked them about this one and am waiting for a response).
>
> So I'm a little confused. Mostly I'm asking to clear up some points in
> a discussion I'm having with somebody on another newsgroup.


Contrary to popular belief, temporaries are not const (unless created
const). However, temporaries do not bind to non-const references. Hence:

typeded std::vector< int > int_vector;
int_vector x;

x.swap( int_vector() ); // illegal
swap( x, int_vector() ); // illegal
int_vector().swap( x ); // legal

In the same way, you can call the assignment operator on a temporary.
(Usually, there is no point in doing so since all effects of the assignment
will be lost at the end of the full expression.)



What is the underlying problem that you are trying to solve?


Best

Kai-Uwe Bux
 
Reply With Quote
 
 
 
 
jason.cipriani@gmail.com
Guest
Posts: n/a
 
      02-19-2008
Thanks for the quick reply!

All right, so... now I have lots of nitpicky questions...

"Kai-Uwe Bux" <(E-Mail Removed)> wrote in message
news:fpe7i8$trk$(E-Mail Removed)...
> (E-Mail Removed) wrote:
>> Would that also be called, officially,
>> a "temporary object"?

>
> a) Yes.


Ok. Now if you have this:

{
SomeThing x;
function1(x);
}

There, x itself is not a "temporary object", right, because you
explicitly
declare it, then use it in another statement -- even though it has a
very
short life. But if you "shorten" that to this:

{
function1(SomeThing());
}

Then that SomeThing you pass to function1 *is* a "temporary object".
The
line is when you ... define the object explicitly in a separate
statement,
so it's lifetime is longer than just the expression it was defined in?
Do I
have that right?

> b) The code should not compile. The temporary does not bind to non-const
> references. See [8.5.3/5].


Thanks for the section reference. I'll read through it tomorrow, it
should
clear up my confusion.

> Nope. You seem to think that something needs to be an l-value to allow for
> assignment. That is not true for class types. For class types, the
> assignment operator is a member function. You can call non-const member
> functions on r-values.


I'm sorry, I don't understand. I'm having a hard time thinking about
this.
When I see people describe what an l-value is, it is usually described
as
"something that can appear on the left side of an = sign". I take that
to
mean "something that can be set equal to something else".

So what you are saying is: Because the assignment operator is a
member
function for class types, a class type does not necessarily have to be
an
"l-value" to appear on the left side of an = sign, because it's just
like
calling any other member function. Since I can do
"SomeThing().SomeMemberFunction();", I can do "SomeThing().operator =
(...);" as well, even though it's not an l-value. Right?

The reason that I thought SomeThing() was an l-value is because it
could
appear on the "left side of an = sign". But, I guess the definition
is
deeper than that. So... what does it take for a class type value to be
an
l-value then? If the fact that the = operator is just another member
function like any other means that "SomeThing() = ...;" does not imply
that
SomeThing() is necessarily an l-value, then it seems like the "=" sign
and
the "l-value-ness" of a class type are completely unrelated concepts?
In
other words, if "SomeThing()" can appear on the left side of an =
sign, but
it is not an l-value, then what *is* an l-value (since being able to
be to
the left of an = is not the only requirement)?

Is it more accurate to say an l-value is "something that can be set
equal to
something else", and not worry about the "=" at all... so it's more
about
the meaning of the statement? What I mean is, if you have a type and
you
implement an = operator for it that does something else that isn't
assignment, then in that case "=" has nothing to do with l-values.
Similarily, if you have a member function, say, "Assign()" that does
do
assignment, then an l-value of that type is a value where it's
meaningful to
call "Assign()" on, even though the assignment operator itself is not
involved?

I am not disagreeing at all -- I'm just trying to wrap my head around
what
you typed, because I'm pretty easily confused.

> Huh? The reason that 2 = 3 does not make sense is that 2 is const. A() is
> not const. Why should it not make sense to set its value?


I'm sorry, "2 = 3" was a really bad example that I used to try to
describe
something that I didn't know the word for. What I meant was something
like
"in most situations, it's a silly thing to do" (for lack of a better
phrase). Sort of like... assuming the = operator for a type has no
side
effects, then doing something like "A() = whatever;" doesn't have any
effect
on your program. If you removed it, everything would still be the
same.
That's kind of more what I meant. It was a very bad example.

> a) gcc also does not compile the code.


> b) Comeau is correct.


It does not compile with GCC... I must have confused myself with
different
test cases. Argh. Thanks for double-checking that.

> Contrary to popular belief, temporaries are not const (unless created
> const). However, temporaries do not bind to non-const references.


I did not think temporaries were const. I think I went the extreme in
the
other direction, trying to assign temporaries to other things. My
logic was
all screwed up. This is what I had thought:

1) L-values are things that appear on the left side of = operators.
2) "(Y(x))" can appear on the left side of = operator.
3) Temporaries are not l-values. Temporaries can not be assigned to
other
things.
4) Therefore, Y(x) is not a "temporary".
5) Therefore, Y(x) can bind to a non-const reference.

But the flaw in that "proof" (of sorts) is that pretty much every
point is
wrong . Because like you said above, the = operator is just
another
non-const member function for class types, nothing special about it.
And
temporaries are not necessarily const.

> Hence:
>
> typeded std::vector< int > int_vector;
> int_vector x;
>
> x.swap( int_vector() ); // illegal
> swap( x, int_vector() ); // illegal
> int_vector().swap( x ); // legal
>
> In the same way, you can call the assignment operator on a temporary.


If you can call the assignment operator on a temporary, why are you
not
allowed to bind temporaries to non-const reference parameters? I mean,
code
like this *seems* entirely reasonable to me:

void function (A &a) {
// do some stuff to a here
}

void function2 (void) {
function(A());
}

Why is that illegal? You create a new A(), pass a reference to it to
function (so it's not copied when you call function(), it's created
before
the actual call is made), it's valid inside function(), you can do
stuff to
it, function() returns, statement ends, A() is destroyed. It doesn't
seem
dangerous, unpredictable, indeterminant, or anything. Do you know why
you
aren't allowed to do that, then (mostly for my own curiosity, I don't
actually have a program that I "need" to do something like that in)?

And since temporaries are not necessarily const, why can they (even
the
non-const ones) only be bound to const references?

> (Usually, there is no point in doing so since all effects of the
> assignment
> will be lost at the end of the full expression.)


*That* is what I was trying to say with the stupid "2=3" example. "No
point". Duh.

> What is the underlying problem that you are trying to solve?


It's an off-topic discussion on a Borland newsgroup about exactly
this
topic. Whether or not you can bind A() to a non-const reference
parameter.
The source of the confusion is two things:

1) I'm not familiar enough with the standard to know what the real,
correct
behavior is, and
2) The Borland compiler *does*, in fact, accept the above code (with
"function(A());").

There was some confusion about which was correct so I asked here to
get a
real answer. The Borland compiler is wrong, of course. It's strange
because
with the [broken] Borland compiler, the following is accepted, like I
said:

struct X { };

struct Y {
Y (const X &) { }
};

void function (Y &) { }

void function2 (void) {
X x;
function(Y(x));
function((Y)x);
}

But this is not (complaining about binding l-values to non-const
references):

struct Y {
};

struct X {
operator Y () { return Y(); }
};

void function (Y &) { }

void function2 (void) {
X x;
function(Y(x));
function((Y)x);
}

The difference being that in the first example the conversion uses
Y's
constructor, but in the second the conversion uses X's cast operator.
It's
totally weird.

Thanks again for your time!
Jason

 
Reply With Quote
 
jason.cipriani@gmail.com
Guest
Posts: n/a
 
      02-19-2008
Sorry about the screwed up line breaks in that last post... don't
blame me, blame it on the fact that computers have been around for a
half a century and nobody's figured out a consistent way to let me
copy and paste text from one text box to another without problems yet.
 
Reply With Quote
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      02-19-2008
(E-Mail Removed) wrote:

> Thanks for the quick reply!
>
> All right, so... now I have lots of nitpicky questions...
>
> "Kai-Uwe Bux" <(E-Mail Removed)> wrote in message
> news:fpe7i8$trk$(E-Mail Removed)...
>> (E-Mail Removed) wrote:
>>> Would that also be called, officially,
>>> a "temporary object"?

>>
>> a) Yes.

>
> Ok. Now if you have this:
>
> {
> SomeThing x;
> function1(x);
> }
>
> There, x itself is not a "temporary object", right, because you
> explicitly
> declare it, then use it in another statement -- even though it has a
> very
> short life. But if you "shorten" that to this:
>
> {
> function1(SomeThing());
> }
>
> Then that SomeThing you pass to function1 *is* a "temporary object".


Yes.

> The
> line is when you ... define the object explicitly in a separate
> statement,
> so it's lifetime is longer than just the expression it was defined in?


Yes. The lifetime of a temporary ends at the full expression with a few
exceptions listed in [12.24].

> Do I
> have that right?


Huh? The right to do what?

[snip]

>> Nope. You seem to think that something needs to be an l-value to allow
>> for assignment. That is not true for class types. For class types, the
>> assignment operator is a member function. You can call non-const member
>> functions on r-values.

>
> I'm sorry, I don't understand. I'm having a hard time thinking about
> this.
> When I see people describe what an l-value is, it is usually described
> as
> "something that can appear on the left side of an = sign". I take that
> to
> mean "something that can be set equal to something else".


One problem is that there is no short definition of l-value and r-value. The
way it formally works is that chapter 5 describes the evaluation of
expressions. For each operator, cast, function call, etc. it describes the
conditions under which it returns an l-value. This yields a recursive
definition that will allow you to deduce for each expression whether it
yields an l-value.

What you heard about l-values being the things that can go on the left
of "=" probably arises from the line

There are several assignment operators, all of which group right-to-left.
All require a modifiable lvalue as their left operand, and the type of an
assignment expression is that of its left operand. [5.17/1]

However, for class types, an expression of the for lhs = rhs does not
invoke an assignment operator but the copy assignment operator.


> So what you are saying is: Because the assignment operator is a
> member
> function for class types, a class type does not necessarily have to be
> an
> "l-value" to appear on the left side of an = sign, because it's just
> like
> calling any other member function. Since I can do
> "SomeThing().SomeMemberFunction();", I can do "SomeThing().operator =
> (...);" as well, even though it's not an l-value. Right?


Yup, that's what I say. May others correct it if I happen to be wrong.


> The reason that I thought SomeThing() was an l-value is because it
> could
> appear on the "left side of an = sign". But, I guess the definition
> is
> deeper than that. So... what does it take for a class type value to be
> an
> l-value then? If the fact that the = operator is just another member
> function like any other means that "SomeThing() = ...;" does not imply
> that
> SomeThing() is necessarily an l-value, then it seems like the "=" sign
> and
> the "l-value-ness" of a class type are completely unrelated concepts?
> In
> other words, if "SomeThing()" can appear on the left side of an =
> sign, but
> it is not an l-value, then what *is* an l-value (since being able to
> be to
> the left of an = is not the only requirement)?


Maybe the closest nut-shell definition of l-value is "an object whose
address can be taken". However, there are, of course issues with this, too:
operator& is also overloadable.


> Is it more accurate to say an l-value is "something that can be set
> equal to
> something else", and not worry about the "=" at all... so it's more
> about
> the meaning of the statement? What I mean is, if you have a type and
> you
> implement an = operator for it that does something else that isn't
> assignment, then in that case "=" has nothing to do with l-values.
> Similarily, if you have a member function, say, "Assign()" that does
> do
> assignment, then an l-value of that type is a value where it's
> meaningful to
> call "Assign()" on, even though the assignment operator itself is not
> involved?


No. Those are technically unrelated to l-valueness. Note that for class
types you can assign to temporaries. That does not make them l-values.


> I am not disagreeing at all -- I'm just trying to wrap my head around
> what
> you typed, because I'm pretty easily confused.
>
>> Huh? The reason that 2 = 3 does not make sense is that 2 is const. A() is
>> not const. Why should it not make sense to set its value?

>
> I'm sorry, "2 = 3" was a really bad example that I used to try to
> describe
> something that I didn't know the word for. What I meant was something
> like
> "in most situations, it's a silly thing to do" (for lack of a better
> phrase). Sort of like... assuming the = operator for a type has no
> side
> effects, then doing something like "A() = whatever;" doesn't have any
> effect
> on your program. If you removed it, everything would still be the
> same.
> That's kind of more what I meant. It was a very bad example.


Well, that depends. Here is another weird example:

typedef std::vector< int > int_vector;
int_vector x;

swap( x, int_vector() ); // illegal
swap( x, int_vector() = int_vector() ); // legal

So, using A() = A(), you can bind a temporary to a non-const reference. Such
trickery can be useful at times (not often!). The reason is that most
classes follow the precedence of the built-in operator= and return a
reference to *this.


[snip]


>> Hence:
>>
>> typeded std::vector< int > int_vector;
>> int_vector x;
>>
>> x.swap( int_vector() ); // illegal
>> swap( x, int_vector() ); // illegal
>> int_vector().swap( x ); // legal
>>
>> In the same way, you can call the assignment operator on a temporary.

>
> If you can call the assignment operator on a temporary, why are you
> not
> allowed to bind temporaries to non-const reference parameters? I mean,
> code
> like this *seems* entirely reasonable to me:
>
> void function (A &a) {
> // do some stuff to a here
> }
>
> void function2 (void) {
> function(A());
> }


It is totally reasonable. The problems stem from "interaction of language
features (misfeatures)".


> Why is that illegal? You create a new A(), pass a reference to it to
> function (so it's not copied when you call function(), it's created
> before
> the actual call is made), it's valid inside function(), you can do
> stuff to
> it, function() returns, statement ends, A() is destroyed. It doesn't
> seem
> dangerous, unpredictable, indeterminant, or anything. Do you know why
> you
> aren't allowed to do that, then (mostly for my own curiosity, I don't
> actually have a program that I "need" to do something like that in)?


The reason that is usually given centers around problems arising from
impicit conversions. Consider:

void inc ( int & i ) {
i += 1;
}

double x;
inc( x );

If the double converts silently to a temporary int and that binds and gets
modified, the results would be surprising.


In any case, C++0X will introduce r-value references that allow temporaries
to bind.


> And since temporaries are not necessarily const, why can they (even
> the
> non-const ones) only be bound to const references?


To avoid the surprises from automatic conversions.



>> (Usually, there is no point in doing so since all effects of the
>> assignment
>> will be lost at the end of the full expression.)

>
> *That* is what I was trying to say with the stupid "2=3" example. "No
> point". Duh.
>
>> What is the underlying problem that you are trying to solve?

>
> It's an off-topic discussion on a Borland newsgroup about exactly
> this
> topic. Whether or not you can bind A() to a non-const reference
> parameter.
> The source of the confusion is two things:
>
> 1) I'm not familiar enough with the standard to know what the real,
> correct
> behavior is, and
> 2) The Borland compiler *does*, in fact, accept the above code (with
> "function(A());").
>
> There was some confusion about which was correct so I asked here to
> get a
> real answer.


Well, [8.5.3/5] describes the precise rules.


[snip]


Best

Kai-Uwe Bux
 
Reply With Quote
 
jason.cipriani@gmail.com
Guest
Posts: n/a
 
      02-19-2008
"Kai-Uwe Bux" <(E-Mail Removed)> wrote in message news:fpedrh$jdj
$(E-Mail Removed)...
>> Do I
>> have that right?

>
> Huh? The right to do what?


LOL... I meant "am I correct".

> Well, that depends. Here is another weird example:
>
> typedef std::vector< int > int_vector;
> int_vector x;
>
> swap( x, int_vector() ); // illegal
> swap( x, int_vector() = int_vector() ); // legal


You're right. That is a weird example. Look, here is a weirder one.
You can do this to accomplish the same thing without creating a second
object or any additional temporaries (aside from whatever swap does):

template <class T> T& abracadabra (const T& v) {
return const_cast<T&>(v);
}

{
A a;
swap(a, abracadabra(A()));
}

That compiles with GCC, and Comeau likes it, too. Only two A's are
created ("a", and the A() passed to swap), and the assignment operator
is called only twice total (at least with the implementation of swap()
GCC comes with).

Thanks a lot for your replies, you answered pretty much all my
questions, the rest I'll figure out once I dig into those sections. I
appreciated it!

Jason
 
Reply With Quote
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      02-19-2008
(E-Mail Removed) wrote:

> "Kai-Uwe Bux" <(E-Mail Removed)> wrote in message news:fpedrh$jdj
> $(E-Mail Removed)...
>>> Do I
>>> have that right?

>>
>> Huh? The right to do what?

>
> LOL... I meant "am I correct".
>
>> Well, that depends. Here is another weird example:
>>
>> typedef std::vector< int > int_vector;
>> int_vector x;
>>
>> swap( x, int_vector() ); // illegal
>> swap( x, int_vector() = int_vector() ); // legal

>
> You're right. That is a weird example. Look, here is a weirder one.
> You can do this to accomplish the same thing without creating a second
> object or any additional temporaries (aside from whatever swap does):
>
> template <class T> T& abracadabra (const T& v) {
> return const_cast<T&>(v);
> }


Ah, the infamous lvalue_cast.


> {
> A a;
> swap(a, abracadabra(A()));
> }
>
> That compiles with GCC, and Comeau likes it, too. Only two A's are
> created ("a", and the A() passed to swap), and the assignment operator
> is called only twice total (at least with the implementation of swap()
> GCC comes with).


It compiles, but it does have undefined behavior. The reason is explained
here:

http://groups.google.com/group/comp....c8fb5450c8182d


However, it will have defined behavior in C++0X according to n2521.


[snip]

Best

 
Reply With Quote
 
jason.cipriani@gmail.com
Guest
Posts: n/a
 
      02-19-2008
On Feb 19, 7:29 am, Kai-Uwe Bux <(E-Mail Removed)> wrote:
> Ah, the infamous lvalue_cast.


Everybody else is always two steps ahead of me!

> It compiles, but it does have undefined behavior. The reason is explained
> here:


Hm, what was an interesting read. What about the following code, is
that defined? I can't imagine a compiler that would be smart enough to
recognize what is going on and create some intermediate object in
between... assuming you haven't overloaded any relevant operators:

template <class T> T& abracadabra (const T& v) {
T *pr;
const T *pv = &v;
memcpy(&pr, &pv, sizeof(T *));
return *pr;
}

Or this... which I guess is different than the above because here you
are still casting away the const, so the compiler could figure out
what is happening (since you aren't hiding it through memcpy)?

template <class T> T& abracadabra (const T& v) {
return *(T *)&v;
}

Jason
 
Reply With Quote
 
jason.cipriani@gmail.com
Guest
Posts: n/a
 
      02-19-2008
On Feb 19, 8:16 am, "(E-Mail Removed)"
<(E-Mail Removed)> wrote:
> template <class T> T& abracadabra (const T& v) {
> T *pr;
> const T *pv = &v;
> memcpy(&pr, &pv, sizeof(T *));
> return *pr;
> }


Rather:

template <class T> T& abracadabra (const T& v) {
union {
T *pr;
const T* pv;
} u;
u.pv = &v;
return *u.pr;
}
 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      02-19-2008
(E-Mail Removed) wrote:
> On Feb 19, 8:16 am, "(E-Mail Removed)"
> <(E-Mail Removed)> wrote:
>> template <class T> T& abracadabra (const T& v) {
>> T *pr;
>> const T *pv = &v;
>> memcpy(&pr, &pv, sizeof(T *));
>> return *pr;
>> }

>
> Rather:
>
> template <class T> T& abracadabra (const T& v) {
> union {
> T *pr;
> const T* pv;
> } u;
> u.pv = &v;
> return *u.pr;


Accessing a member of a union that you didn't store in it has
undefined behaviour. Why don't you simply const_cast it?

> }


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


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
anonymous array of strings // ("taking address of temporary"- how long is temporary valid?) anon.asdf@gmail.com C++ 7 02-12-2008 10:58 AM
temporary desktop shortcut Lou Firefox 3 08-03-2005 02:30 PM
Temporary Files Harsh Vardhan Singh ASP .Net 4 03-09-2005 01:48 PM
T'Bird + Temporary groups. Gavern Firefox 1 11-29-2004 01:41 PM
Need Temporary VPN Solution During Move sid Cisco 3 08-13-2004 05:12 PM



Advertisments