Mutating temporaries ?!?

S

Samee Zahur

Hi all,
We know that if a function returns by value, assigning to that value
or changing it in any way is meaningless. For example:

int fun();

....

fun()=43; //Definitely an error!!

It is almost (though not quite) as if the return value is a
'const int' rather than a simple 'int' (OK, it's not an l-value).

However, if an object of user-defined type is being returned by
value, none of it's non-const functions are barred from being called.
For example,

class test
{
int a;
public:
test():a(5) {}
void mutate() {a=45;} //mutate() is NOT const
int get() const {return a;}
};

test fun(){return test();}

void main()
{
int i=fun().get(); //Valid, no problem
fun().mutate(); //Why is this valid???
}


Shouldn't only const member functions be allowed on something
that isn't even an l-value?? What if test overloaded the assignment=
operator like this:

test& operator=(int b); //non-const obviously

Would that mean fun()=30; becomes valid above? Why is something like
this allowed?

Samee

P.S. I really do not have a copy of the standard, but I'm assuming
this is right because I trust g++ to be standard-conforming enough.
Please correct me if I am wrong in this case.
 
R

Richard Herring

In message said:
Hi all,
We know that if a function returns by value, assigning to that value
or changing it in any way is meaningless. For example:

int fun();

...

fun()=43; //Definitely an error!!

It is almost (though not quite) as if the return value is a
'const int' rather than a simple 'int' (OK, it's not an l-value).

However, if an object of user-defined type is being returned by
value, none of it's non-const functions are barred from being called.
For example,

class test
{
int a;
public:
test():a(5) {}
void mutate() {a=45;} //mutate() is NOT const
test & mutate() { a = 45; return *this; }
void put(std::eek:stream & str) const { str << a; }
int get() const {return a;}
};

test fun(){return test();}

void main()
{
int i=fun().get(); //Valid, no problem
fun().mutate(); //Why is this valid???

fun().mutate().put(std::cout); // Why shouldn't this be valid?
 
H

Howard

Samee Zahur said:
Hi all,
We know that if a function returns by value, assigning to that value
or changing it in any way is meaningless. For example:

int fun();

...

fun()=43; //Definitely an error!!

It is almost (though not quite) as if the return value is a
'const int' rather than a simple 'int' (OK, it's not an l-value).

However, if an object of user-defined type is being returned by
value, none of it's non-const functions are barred from being called.
For example,

class test
{
int a;
public:
test():a(5) {}
void mutate() {a=45;} //mutate() is NOT const
int get() const {return a;}
};

test fun(){return test();}

void main()
{
int i=fun().get(); //Valid, no problem
fun().mutate(); //Why is this valid???
}


Shouldn't only const member functions be allowed on something
that isn't even an l-value?? What if test overloaded the assignment=
operator like this:

test& operator=(int b); //non-const obviously

Would that mean fun()=30; becomes valid above? Why is something like
this allowed?

Samee

P.S. I really do not have a copy of the standard, but I'm assuming
this is right because I trust g++ to be standard-conforming enough.
Please correct me if I am wrong in this case.

Yes, that's fine. And the reason is that = is an operator for the class
test. While logically it may seem right to restrict the assignment operator
from that kind of usage, there's no reason, in general, why you would need
to prevent calling functions (including member operators) on a user-defined
class. Chaining calls together like you've shown is fine (provided the
functions return non-const results). I don't do it in general, because I
just prefer to do one thing at a time, even if it means assigning an
otherwise temporary value to a local variable. (Mostly, it helps me debug.)
If you want to prevent that for your own classes, then just make the return
values const.

-Howard
 
R

Ron Natalie

Samee said:
Hi all,
We know that if a function returns by value, assigning to that value
or changing it in any way is meaningless. For example:

int fun();

...

fun()=43; //Definitely an error!!

It is almost (though not quite) as if the return value is a
'const int' rather than a simple 'int' (OK, it's not an l-value).
For class types, why should you be allowed to perform operations
on the temporaries. It's useful. For example, you may wish to
return a helper object that you can assign into to emulate assignment
into a more complex object. vector<bool> operator[] is an example.
 
S

Samee Zahur

True ... It can be useful ... but for operator[] or things like that, a
return by reference is usually more common. But it is still a little
uneasy for me that a return by value cannot be modified for built-in
types but works fine for my types.
 

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

Members online

No members online now.

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,228
Latest member
MikeMichal

Latest Threads

Top