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 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! 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 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
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
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?
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
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
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 This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
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...
|
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...
|
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...
|
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...
|
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...
|
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...
|
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....
|
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...
|
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...
|
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...
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
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...
|
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,...
|
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...
|
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...
|
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...
|
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...
|
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...
| |