 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Peer Georgi Guest
|
Posted: Fri Nov 11, 2005 12:12 pm Post subject: uninitialized referance: Is this valid c++ |
|
|
Please look at the following code sequence:
int giAnyValidObject = 42;
double gdAnyValidObject = 42.0;
int* createObject(const int&)
{
// any valid int object //
return &giAnyValidObject;
}
double* createObject(const double&)
{
// any valid double object //
return &gdAnyValidObject;
}
int main(int, char**)
{
// .. //
// passing the invalid reference "i" as argument for createObject...
int& i = *createObject(i);
// .. //
}
// -- this compiles successfully -- //
My question is about the (uninitialized) reference given as
argument for "createObject".
The compiler does not throw any warnings about it and
I need this argument to let the compiler decide which overloaded
version of "createObject" to use...
Does this conform to the c++ standard or is my compiler (gcc-3.3.6) the only
one building this ?
Regards,
Peer.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Thomas Richter Guest
|
Posted: Sat Nov 12, 2005 10:28 am Post subject: Re: uninitialized referance: Is this valid c++ |
|
|
Hi,
| Quote: | int giAnyValidObject = 42;
double gdAnyValidObject = 42.0;
int* createObject(const int&)
{
// any valid int object //
return &giAnyValidObject;
}
double* createObject(const double&)
{
// any valid double object //
return &gdAnyValidObject;
}
int main(int, char**)
{
// .. //
// passing the invalid reference "i" as argument for createObject...
int& i = *createObject(i);
// .. //
}
My question is about the (uninitialized) reference given as
argument for "createObject".
The compiler does not throw any warnings about it
|
Warnings are completely optional, a compiler may or may not warn.
However, the code itself is syntatically correct, thus there's no
error here. In fact, as you don't use the referenced object in
"createObject()" either, there's no undefined behaivour here as well.
| Quote: | and I need this argument to let the compiler decide which overloaded
version of "createObject" to use...
|
I don't understand? The function to call is choosen by static type
information.
| Quote: | Does this conform to the c++ standard
|
Yes. Except that your main should return something (the return statement
is missing. ;-)
So long,
Thomas
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ulrich Eckhardt Guest
|
Posted: Sat Nov 12, 2005 10:29 am Post subject: Re: uninitialized referance: Is this valid c++ |
|
|
Peer Georgi wrote:
| Quote: | int* createObject(const int&)
[...]
double* createObject(const double&)
[...]
// passing the invalid reference "i" as argument for createObject...
int& i = *createObject(i);
[...]
My question is about the (uninitialized) reference given as
argument for "createObject".
The compiler does not throw any warnings about it and
I need this argument to let the compiler decide which overloaded
version of "createObject" to use...
|
I can't strictly answer your question, though I think it's OK. However,
there are alternatives:
1. Simply call the function with a temporary:
int& i = *createObject(int());
float& f = *createObject(float());
2. Use a template function:
template<typename T>
T* createObject();
int& i = *createObject<int>();
float& f = *createObject<float>();
Note: In case you need this second form to work with VC6 or eVC4, you can
add a dummy parameter:
template<typename T>
T*
#if defined(_MSC_VER) && _MSC_VER<1300
createObject( T const* dummy = 0);
#else
// see above
#endif
Uli
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
johnchx2@yahoo.com Guest
|
Posted: Sat Nov 12, 2005 10:30 am Post subject: Re: uninitialized referance: Is this valid c++ |
|
|
Peer Georgi wrote:
| Quote: | My question is about the (uninitialized) reference given as
argument for "createObject".
The compiler does not throw any warnings about it and
|
The standards committee appears to believe that this is perfectly fine:
http://www2.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#363
I don't agree with their reading of 3.8/6, and I think it's a very bad
idea to allow this. But I don't get to vote on the matter. :-)
| Quote: | I need this argument to let the compiler decide which overloaded
version of "createObject" to use...
|
Well, you *could* use a pointer rather than a reference, which would
avoid potentially running afoul of 8.3.2/4 ("A reference shall be
initialized to refer to a valid object or function.")
There's a slightly more elaborate solution that allows you to simulate
overloading on the return type (which is what it looks like you're
trying to accomplish). The general idea is to return a proxy object
from your function which has implicit conversions to the types you're
interested in. The conversion operators do the real work.
To illustrate with your example:
#include <iostream>
int gi = 42;
double gd = 42.0;
class proxy {
public:
operator int& () const { return gi; }
operator double& () const { return gd; }
};
proxy create_object()
{
return proxy();
}
int main()
{
int& i = create_object();
double& j = create_object();
gi = 100;
gd = 99.9;
std::cout << "i: " << i << " j: " << j << std::endl;
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Victor Bazarov Guest
|
Posted: Sat Nov 12, 2005 10:33 am Post subject: Re: uninitialized referance: Is this valid c++ |
|
|
Peer Georgi wrote:
| Quote: | Please look at the following code sequence:
int giAnyValidObject = 42;
double gdAnyValidObject = 42.0;
int* createObject(const int&)
{
// any valid int object //
return &giAnyValidObject;
}
double* createObject(const double&)
{
// any valid double object //
return &gdAnyValidObject;
}
int main(int, char**)
{
// .. //
// passing the invalid reference "i" as argument for
createObject... int& i = *createObject(i);
// .. //
}
// -- this compiles successfully -- //
My question is about the (uninitialized) reference given as
argument for "createObject".
The compiler does not throw any warnings about it and
I need this argument to let the compiler decide which overloaded
version of "createObject" to use...
Does this conform to the c++ standard or is my compiler (gcc-3.3.6)
the only one building this ?
|
The uninitialised reference is not being used in any way, so there
is no big deal. The code is valid (well-formed) and even has well-
defined behaviour. Actually, to make it not use an uninitialised
reference, you could write
int& i = *createObject(0);
since 0 has type 'int' and is convertible to a const ref. And for
double you could do
double& d = *createObject(0.0);
since 0.0 has type 'double'.
But I am sure your program uses more complicated types than just
double or int, right? Use your method, then, it's fine.
V
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Jakob Bieling Guest
|
Posted: Sun Nov 13, 2005 3:37 pm Post subject: Re: uninitialized referance: Is this valid c++ |
|
|
"Thomas Richter" <thor (AT) mersenne (DOT) math.TU-Berlin.DE> wrote
| Quote: | int main(int, char**)
{
// .. //
}
your main should return something (the return statement
is missing.
|
Omitting the return statement is actually valid for the main
function.
regards
--
jb
(reply address in rot13, unscramble first)
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Gene Bushuyev Guest
|
Posted: Sun Nov 13, 2005 3:38 pm Post subject: Re: uninitialized referance: Is this valid c++ |
|
|
<johnchx2 (AT) yahoo (DOT) com> wrote
| Quote: | Peer Georgi wrote:
My question is about the (uninitialized) reference given as
argument for "createObject".
The compiler does not throw any warnings about it and
The standards committee appears to believe that this is perfectly fine:
http://www2.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#363
I don't agree with their reading of 3.8/6, and I think it's a very bad
idea to allow this. But I don't get to vote on the matter.
|
I think I don't agree with that resolution either.
"It's permitted to take the address of a class object before it is fully
initialized, and it's permitted to pass it as an argument to a reference
parameter as long as the reference can bind directly."
Which is a correct statement, but it's incomplete. Because the undefined
behavior doesn't come from reference binding, but from l-value to r-value
conversion in the provided example.
In the OP example, there is a qualification conversion from reference to const
reference. Is it an l-value to r-value conversion? I think it is, it's not a
direct reference binding that the standard exempts from l- to r- conversion.
Don't have the standard at hand to check what it says about qualification
conversions, so don't beat me up if I'm wrong here :-)
-- Gene Bushuyev
----------------------------------------------------------------
There is no greatness where there is no simplicity, goodness and truth. ~ Leo
Tolstoy
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Victor Bazarov Guest
|
Posted: Sun Nov 13, 2005 3:41 pm Post subject: Re: uninitialized referance: Is this valid c++ |
|
|
Thomas Richter wrote:
| Quote: | Does this conform to the c++ standard
Yes. Except that your main should return something (the return
statement is missing.
|
It's allowed to omit the return statement in 'main'. Falling off the
end of 'main' is equivalent of returning 0.
V
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Gene Bushuyev Guest
|
Posted: Sun Nov 13, 2005 10:51 pm Post subject: Re: uninitialized referance: Is this valid c++ |
|
|
"Gene Bushuyev" <spam (AT) spamguard (DOT) com> wrote
[...]
| Quote: | The standards committee appears to believe that this is perfectly fine:
http://www2.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#363
I don't agree with their reading of 3.8/6, and I think it's a very bad
idea to allow this. But I don't get to vote on the matter. :-)
I think I don't agree with that resolution either.
"It's permitted to take the address of a class object before it is fully
initialized, and it's permitted to pass it as an argument to a reference
parameter as long as the reference can bind directly."
Which is a correct statement, but it's incomplete. Because the undefined
behavior doesn't come from reference binding, but from l-value to r-value
conversion in the provided example.
|
I wasn't very attentive writing my previous reply. There was no l-value to
r-value conversion in that example. So the resolution was correct. Which raises
the question if the standard is consistent in its treatment of uninitialized
variables. Example,
void f1(int i) { cout << "hello"; }
void f2(const int& i) { cout << "hello"; }
void foo()
{
int a;
f1(a); // u.b.
f2(a); // ok
}
functions f1() and f2() are similar, in fact compiler will probably produce the
same code. But f1() introduces undefined behavior because of l-to-r-value
conversion, while in f2() the reference is bound directly, no conversion is
done, so it has no undefined behavior. That's weird.
-- Gene Bushuyev
----------------------------------------------------------------
There is no greatness where there is no simplicity, goodness and truth. ~ Leo
Tolstoy
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Sumanth Guest
|
Posted: Sun Nov 13, 2005 10:52 pm Post subject: Re: uninitialized referance: Is this valid c++ |
|
|
int giAnyValidObject = 42;
double gdAnyValidObject = 42.0;
int* createObject(const int&)
{
// any valid int object //
return &giAnyValidObject;
}
double* createObject(const double&)
{
// any valid double object //
return &gdAnyValidObject;
}
int main(int, char**)
{
// .. //
// passing the invalid reference "i" as argument for
createObject...
int& i = *createObject(i);
// .. //
}
int& i = *createObject(i);
This is a valid call, the c compiler will not have any problem calling
the function.
You are doing a call by reference .
I can't see a problem with this.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Peer Georgi Guest
|
Posted: Mon Nov 14, 2005 4:48 pm Post subject: Re: uninitialized referance: Is this valid c++ |
|
|
Thanks to all replied to my question!
[email]johnchx2 (AT) yahoo (DOT) com[/email] wrote:
| Quote: | ...
There's a slightly more elaborate solution that allows you to simulate
overloading on the return type (which is what it looks like you're
trying to accomplish). The general idea is to return a proxy object
from your function which has implicit conversions to the types you're
interested in. The conversion operators do the real work.
...
|
The idea with a proxy class is very nice but not realy usable because a new
type supported forces the change of one central class (the proxy class).
The following peace of code will show why "createObject" method must(?)
be called with a not fully initialized reference of "Type".
// ... the template version of my createObject
template<class Type>
Type* createObject(const Type&)
{
Type* p = new Type();
return (p);
}
// ... a template for use with references or plain types
template<class Type>
class cClass
{
public:
void foo()
{
Type tmp = *createObject(tmp);
// do anythink with tmp and destroy it //
// ...
// NOTE: the way of destroying tmp is NOT descripted here
}
};
int main(int, char**)
{
{ // it have to work with reference types
cClass<int&> object1;
object1.foo();
}
{ // it have to work with other types too
cClass<int> object2;
object2.foo();
}
return (123454321);
}
[email]johnchx2 (AT) yahoo (DOT) com[/email] wrote:
I understand bad feeling about it but in this case it is only way to solve
the given problem. (Please write if I'm wrong...)
Best Regards,
Peer
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Kd Guest
|
Posted: Wed Nov 16, 2005 12:42 am Post subject: Re: uninitialized referance: Is this valid c++ |
|
|
Wait a sec. I am lil confused. Are you trying to use reference and
plain types interchangably in this context?
Because all that seems to be happening by doing
template<class Type>
Type* createObject(const Type&)
{
Type* p = new Type();
return (p);
}
is that compiler inside the function "forgets" that the Type was int&
and uses it as int.
Regards,
K
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
johnchx2@yahoo.com Guest
|
Posted: Wed Nov 16, 2005 12:44 am Post subject: Re: uninitialized referance: Is this valid c++ |
|
|
Peer Georgi wrote:
| Quote: | Thanks to all replied to my question!
[email]johnchx2 (AT) yahoo (DOT) com[/email] wrote:
...
There's a slightly more elaborate solution that allows you to simulate
overloading on the return type (which is what it looks like you're
trying to accomplish). The general idea is to return a proxy object
from your function which has implicit conversions to the types you're
interested in. The conversion operators do the real work.
...
The idea with a proxy class is very nice but not realy usable because a new
type supported forces the change of one central class (the proxy class).
|
Not necessarily...conversion operators can be templates too. And
sometimes having a central point of control over such functions is
exactly what you want...it depends on the overall design.
| Quote: | The following peace of code will show why "createObject" method must(?)
be called with a not fully initialized reference of "Type".
// ... the template version of my createObject
template<class Type
Type* createObject(const Type&)
{
Type* p = new Type();
return (p);
}
// ... a template for use with references or plain types
template
class cClass
{
public:
void foo()
{
Type tmp = *createObject(tmp);
// do anythink with tmp and destroy it //
// ...
// NOTE: the way of destroying tmp is NOT descripted here
}
};
int main(int, char**)
{
{ // it have to work with reference types
cClass
object1.foo();
}
{ // it have to work with other types too
cClass<int> object2;
object2.foo();
}
return (123454321);
}
|
I think I see what you're getting at: you're using the reference
parameter as a way to perform a remove_ref operation. That is, you
want CreateObject() to call "new int" whether it's instantiated with
int or int& (because you can't call "new int&").
There's another way to do that:
// a quick-and-dirty RemoveRef implementation
template < class T >
struct RemoveRef {
typedef T type;
};
template < class T >
struct RemoveRef< T& > {
typedef T type;
};
// define the CreateObject() function template
template < class T >
typename RemoveRef<T>::type*
CreateObject()
{
return new typename RemoveRef<T>::type();
}
// use the CreateObject() function template
int main()
{
int& ir = *CreateObject<int&>();
int i = *CreateObject<int>();
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|