C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

uninitialized referance: Is this valid c++

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Peer Georgi
Guest





PostPosted: Fri Nov 11, 2005 12:12 pm    Post subject: uninitialized referance: Is this valid c++ Reply with 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 ?

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





PostPosted: Sat Nov 12, 2005 10:28 am    Post subject: Re: uninitialized referance: Is this valid c++ Reply with quote



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





PostPosted: Sat Nov 12, 2005 10:29 am    Post subject: Re: uninitialized referance: Is this valid c++ Reply with quote



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





PostPosted: Sat Nov 12, 2005 10:30 am    Post subject: Re: uninitialized referance: Is this valid c++ Reply with quote

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





PostPosted: Sat Nov 12, 2005 10:33 am    Post subject: Re: uninitialized referance: Is this valid c++ Reply with quote

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





PostPosted: Sun Nov 13, 2005 3:37 pm    Post subject: Re: uninitialized referance: Is this valid c++ Reply with quote

"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. Wink


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





PostPosted: Sun Nov 13, 2005 3:38 pm    Post subject: Re: uninitialized referance: Is this valid c++ Reply with quote

<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. Smile

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





PostPosted: Sun Nov 13, 2005 3:41 pm    Post subject: Re: uninitialized referance: Is this valid c++ Reply with quote

Thomas Richter wrote:
Quote:
Does this conform to the c++ standard

Yes. Except that your main should return something (the return
statement is missing. Wink

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





PostPosted: Sun Nov 13, 2005 10:51 pm    Post subject: Re: uninitialized referance: Is this valid c++ Reply with quote

"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





PostPosted: Sun Nov 13, 2005 10:52 pm    Post subject: Re: uninitialized referance: Is this valid c++ Reply with 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);
// .. //
}
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





PostPosted: Mon Nov 14, 2005 4:48 pm    Post subject: Re: uninitialized referance: Is this valid c++ Reply with quote

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:
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. Smile

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





PostPosted: Wed Nov 16, 2005 12:42 am    Post subject: Re: uninitialized referance: Is this valid c++ Reply with quote

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





PostPosted: Wed Nov 16, 2005 12:44 am    Post subject: Re: uninitialized referance: Is this valid c++ Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.