473,413 Members | 2,044 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,413 software developers and data experts.

insertion operator and const reference

Hello All,

I need your help in understanding something.

I have a simple class

class test{

};

And I also have a simple insertion operator:

ostream& operator<<(ostream& out, test &a){
out<<"testing";
}

(it is just for testing.)
Note that I do not have const reference to the "test" object in the
insertion operator function.

Now from another function (say main), I have this

int main(){
test a
cout<<a<<endl;

return 0;

}

It works fine, and I get "testing" as output.

But if I have a function say:

test f(){
test a;
return a;
}

[this returns a test object]

and have my main as this:

int main(){

cout<<f()<<endl;

return 0;

}

I get errors!!!, and top errors says I don't have a matching operator<<
in std:cout<<f()()

Now what is that? and why is that?

To fix it, I pass the test object in insertion operator as *const*
reference. It all works. Even if I pass test object by value, its
works!.

So whats the deal? Is there something special when returing an object
from a function?

BTW: I do send objects as const references whenever possible, but why
should it be *necessary* to send as const?

Thanks
Bipod

Oct 23 '05 #1
8 2726
Just tested another thing. It above problem exists when working it
temporary objects.

So if insertion operator takes the object as reference (and not as
const reference or copy), the following would not work either

int main(){
cout<<test()<<endl;
}

It gives the same error message.

Don't know why though!

Oct 23 '05 #2

bi***********@gmail.com wrote:
Just tested another thing. It above problem exists when working it
temporary objects.

So if insertion operator takes the object as reference (and not as
const reference or copy), the following would not work either

int main(){
cout<<test()<<endl;
}

It gives the same error message.

Don't know why though!

cout<<f(); returns a temprary object whose life is at the stament
level: it will be destroyed at the end of the statement that is.

a. if pass by value, object is copied to the function's paramer value -
that is fine

b. passing by const reference is also fine

c. however, if you pass by reference, in the function you will can
modify unmodifyalbe object - ICEURN!
Easier: you f() returns [temp] const test obeject

f(test t) is fine, since you're not modifying object directly,
f(const t &) is fine, since you promise that object won't be modified.
f(t &) here is make no promises, thus violating const-correctness.
for ref. http://www.parashift.com/c++-faq-lit...rrectness.html

Oct 23 '05 #3
bi***********@gmail.com wrote:
Just tested another thing. It above problem exists when working it
temporary objects.

So if insertion operator takes the object as reference (and not as
const reference or copy), the following would not work either

int main(){
cout<<test()<<endl;
}


The slogan is: you cannot bind a temporary to a non-const reference. The
precise rules are in 8.5.3/5 of the standard which is a pain to read. Do
not ask me for a rational: I have no idea why this restriction exists. But
it is easily circumvented:

/*
| lvalue_cast( non-const expression ) creates an lvalue out
| of anything, including a temporary. Just make sure, the
| expression is not constant.
*/

template < typename T >
T & lvalue_cast ( const T & ref ) {
return( const_cast< T & >( ref ) );
}

Another trick that you can try is this:

std::cout<< std::dec << test() << std::endl;

Now, why this works is explained somewhere in the archives of this news
group :-)
Best

Kai-Uwe Bux
Oct 23 '05 #4
puzzlecracker wrote:

bi***********@gmail.com wrote:
Just tested another thing. It above problem exists when working it
temporary objects.

So if insertion operator takes the object as reference (and not as
const reference or copy), the following would not work either

int main(){
cout<<test()<<endl;
}

It gives the same error message.

Don't know why though!

cout<<f(); returns a temprary object whose life is at the stament
level: it will be destroyed at the end of the statement that is.

a. if pass by value, object is copied to the function's paramer value -
that is fine

b. passing by const reference is also fine

c. however, if you pass by reference, in the function you will can
modify unmodifyalbe object - ICEURN!

Nope: temporaries are not unmodifiable. It just so happens that it is
usually pointless to modify them. However, you could do funny stuff using
static members or side effects of the destructor. In any case, temporaries
can be modified:

#include <iostream>

struct xxx {

static int s;

int l;

xxx ( int i )
: l ( i )
{}

~xxx ( void ) {
std::cout << "local: " << l << '\n';
}
void modify ( int i ) {
l = i;
s = i;
}

};

int xxx::s = 0;

int main ( void ) {
xxx( 3 ).modify( 5 );
std::cout << "static: " << xxx::s << '\n';
}
prints:
a.out

local: 5
static: 5
[snip]
And, what is the meaning of ICEURN?
Best

Kai-Uwe Bux
Oct 23 '05 #5

Kai-Uwe Bux wrote:
puzzlecracker wrote:

bi***********@gmail.com wrote:
Just tested another thing. It above problem exists when working it
temporary objects.

So if insertion operator takes the object as reference (and not as
const reference or copy), the following would not work either

int main(){
cout<<test()<<endl;
}

It gives the same error message.

Don't know why though!

cout<<f(); returns a temprary object whose life is at the stament
level: it will be destroyed at the end of the statement that is.

a. if pass by value, object is copied to the function's paramer value -
that is fine

b. passing by const reference is also fine

c. however, if you pass by reference, in the function you will can
modify unmodifyalbe object - ICEURN!

Nope: temporaries are not unmodifiable. It just so happens that it is
usually pointless to modify them. However, you could do funny stuff using
static members or side effects of the destructor. In any case, temporaries
can be modified:

#include <iostream>

struct xxx {

static int s;

int l;

xxx ( int i )
: l ( i )
{}

~xxx ( void ) {
std::cout << "local: " << l << '\n';
}
void modify ( int i ) {
l = i;
s = i;
}

};

int xxx::s = 0;

int main ( void ) {
xxx( 3 ).modify( 5 );
std::cout << "static: " << xxx::s << '\n';
}
prints:
a.out

local: 5
static: 5
[snip]
And, what is the meaning of ICEURN?
Best

Kai-Uwe Bux


I don't agree with this trick as a modification of the temporary. All
modification was done at the statement level, which was expectedly
followed by the destruction of the object - that is allowed.
Furthermore, you modified static member, which doesn't belong to the
temporary. You used temporary as a proxy to modify static mem.
variable. Were you to declare that variable as a const temporary,
modify() member function wouldn't have been invoked. Agree?

What is the with std:dec? I had never heard of it?
Mind to elaborate?

Oct 23 '05 #6
puzzlecracker wrote:
[...]
I don't agree with this trick as a modification of the temporary.
What is it, then?
All
modification was done at the statement level, which was expectedly
followed by the destruction of the object - that is allowed.
Uh... So, you concede that modification was, in fact, done?
Furthermore, you modified static member, which doesn't belong to the
temporary.
Kai-Uwe modified both.
You used temporary as a proxy to modify static mem.
variable.
No, not just as a proxy. Read the example again.
Were you to declare that variable as a const temporary,
modify() member function wouldn't have been invoked. Agree?
What's a "const temporary" and how do you "declare" one? The syntax used
in the example ("<type-id>()") is not a declaration and it cannot create
a const object. And yes, if the class had two overloaded functions, one
const and the other non-const, a non-const function is preferred even for
a temporary; exactly because the temporary in _that_case_ is non-const.
What is the with std:dec? I had never heard of it?
Mind to elaborate?


(a) It's 'std::dec'
(b) It's called "I/O manipulator". Read up on them.

V
Oct 23 '05 #7
puzzlecracker wrote:

Kai-Uwe Bux wrote:
puzzlecracker wrote: [snip]
> c. however, if you pass by reference, in the function you will can
> modify unmodifyalbe object - ICEURN!

Nope: temporaries are not unmodifiable. It just so happens that it is
usually pointless to modify them. However, you could do funny stuff using
static members or side effects of the destructor. In any case,
temporaries can be modified:

#include <iostream>

struct xxx {

static int s;

int l;

xxx ( int i )
: l ( i )
{}

~xxx ( void ) {
std::cout << "local: " << l << '\n';
}
void modify ( int i ) {
l = i;
s = i;
}

};

int xxx::s = 0;

int main ( void ) {
xxx( 3 ).modify( 5 );
std::cout << "static: " << xxx::s << '\n';
}
prints:
> a.out

local: 5
static: 5
[snip]
And, what is the meaning of ICEURN?
Best

Kai-Uwe Bux


I don't agree with this trick as a modification of the temporary. All
modification was done at the statement level, which was expectedly
followed by the destruction of the object - that is allowed.


Well, all modifications of objects are expectedly followed by the
destruction of the object: you cannot modify an object after it died, and
every object dies eventually, unless you call exit.
Furthermore, you modified static member, which doesn't belong to the
temporary. You used temporary as a proxy to modify static mem.
variable. Were you to declare that variable as a const temporary,
modify() member function wouldn't have been invoked.
What is a const temporary? I called a non-const function of an object. To
the compiler that is a possibly modifying operation. The object was a
temporary. Thus, modifying a temporary is legal.
Agree?
No, the object was modified during its lifetime -- like any other object.
That the lifetime of the object is just one statement is immaterial. I
could make that statement last for the execution of the whole program:

int dummy_main ( void ) {
here goes the real program
}

int main ( void ) {
temporary().modify(), dummy_main();
}

More important, though, is that the modifications of the temporary can have
effects that survive: consider

struct xxx {

some_type* a_pointer;

xxx ( some_type* ptr )
: a_pointer( ptr )
{}

void modify ( ... ) {
do something to the pointee
*a_pointer
}

};

Now, modification of the object has side effects.
Of course, you can always twist language to not say that the temporary is
modified. However, I find it more easy to go with a conventional meaning of
modification: change of a property over time. So here is something more
obvious:

#include <iostream>

struct xxx {

int l;

xxx ( int i )
: l ( i )
{}

xxx& print( void ) {
std::cout << l << '\n';
return( *this );
}

xxx& modify ( int i ) {
l = i;
return( *this );
}

};

int main ( void ) {
xxx( 3 ).print().modify( 5 ).print().modify(1).print();
}
a.out
3
5
1

I would consider it a stretch of language to maintain that the temporary is
*not* modified although the value of its member variable clearly changes
twice.

What is the with std:dec? I had never heard of it? Mind to elaborate?


It's an io-manipulator. The effect is that numbers are printed in base 10,
which is the default anyway: so you won't notice the difference.

However, I have to retract my claim that

std::cout << std::dec << temp() << '\n';

would work. I confused it with something else: piping something to a
temporary stream object. For that, you might want to google "tricky
stringstream-based temporary" in the archive for this group. In that
thread, many people (Siemel Naran in particular) explained kindly to me why
and how that works. You will also find that the technique described in that
thread illustrates the use of modifying temporaries.
Best

Kai-Uwe Bux
Oct 23 '05 #8
Kai-Uwe Bux wrote:
bi***********@gmail.com wrote: [snip] Another trick that you can try is this:

std::cout<< std::dec << test() << std::endl;


Oops, I got confused. The std::dec applies to the situation where the stream
is a temporary:
#include <fstream>

int main ( void ) {
std::ofstream( "test.001" ) << std::dec << "hello world!" << '\n';
std::ofstream( "test.002" ) << "hello world!" << '\n';
}
On my machine, this does:

test.001: hello world!
test.002: 0x8048a01

So the first line prints the string whereas the second prints the pointer to
the string (in a way that is up to the implementation).
Best

Kai-Uwe Bux
Oct 24 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: cpp | last post by:
Ok, I have been tearing my hair out trying to get this to work, so anything you can do I will greatly appreciate. I have this small class which is supposed to make, for its users, outputting to a...
18
by: cppaddict | last post by:
Hi, Is it considered bad form to have the subscript operator return a const reference variable? If not, what is the proper way to do it? My question was prompted by the code below, my...
2
by: ryan.fairchild | last post by:
I have a problem I am trying to create a MyInt class to hanlde very large ints. Its for a class, therefore I can only do what the teach tells me. I want to be able to overload the insertion...
20
by: Patrick Guio | last post by:
Dear all, I have some problem with insertion operator together with namespace. I have a header file foo.h containing declaration of classes, typedefs and insertion operators for the typedefs in...
4
by: Raider | last post by:
Is there std::map member-function that do as code below? typedef std::map<NameClass, ValueClass> ParameterContainer; .... // this code is equivalent to "_Parameters = Value", // but a bit...
2
by: B. Williams | last post by:
I have an assignment for school to Overload the operators << and >and I have written the code, but I have a problem with the insertion string function. I can't get it to recognize the second of...
5
by: Naveen | last post by:
I am trying to write a conatiner which has std::map like methods but preserves the order of insertion. TO achieve this I thought of providing my own function for comparing the keys of the map....
5
by: raylopez99 | last post by:
I need an example of a managed overloaded assignment operator for a reference class, so I can equate two classes A1 and A2, say called ARefClass, in this manner: A1=A2;. For some strange reason...
5
by: phiefer3 | last post by:
I'm currently a student, but this problem isn't directly related to what I have to do on an assignment. It's just a problem I've had with some supporting features. First of all, I'm using MSVS...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.