function returning reference to empty object

D

Dejfson

Dear All,
can someone clarify me how to return the reference to the empty object
in case of error?

_not working_ Example of what i'd like to do:


const MyClassData& MyClass ()
{
QListIterator<MyClassData> it(fancylist)

while (it.hasNext())
{
const MyClassData &data = it.next();

if (data are ok)
return data;
}

return MyClassData();
}



This compiles, but of course it returns invalid reference in the case
when I don't find any suitable data. It there a way how to use the
reference in such case??

I have just one solution in my mind: if I create class variable:

class MyClass {
public:
MyClass () : errorVariable() {};

private:
MyClassData errorVariable;
}


and then I modify function:


const MyClassData& MyClass ()
{
QListIterator<MyClassData> it(fancylist)

while (it.hasNext())
{
const MyClassData &data = it.next();

if (data are ok)
return data;
}

return errorVariable;
}



But I'm not sure whether I like the idea of creating additional variable
just as placeholder for something which doesn't really exist..


Is there another way?

thx
d.
 
V

Victor Bazarov

Dejfson said:
Dear All,
can someone clarify me how to return the reference to the empty object
in case of error?
throw.

_not working_ Example of what i'd like to do:


const MyClassData& MyClass ()
{
QListIterator<MyClassData> it(fancylist)

while (it.hasNext())
{
const MyClassData &data = it.next();

if (data are ok)
return data;
}

return MyClassData();
}



This compiles, but of course it returns invalid reference in the case
when I don't find any suitable data. It there a way how to use the
reference in such case??

I have just one solution in my mind: if I create class variable:

class MyClass {
public:
MyClass () : errorVariable() {};

private:
MyClassData errorVariable;

No need to make it non-static.
}


and then I modify function:


const MyClassData& MyClass ()
{
QListIterator<MyClassData> it(fancylist)

while (it.hasNext())
{
const MyClassData &data = it.next();

if (data are ok)
return data;
}

return errorVariable;
}



But I'm not sure whether I like the idea of creating additional
variable just as placeholder for something which doesn't really
exist..

Is there another way?

Your class can have a static instance of itself, something like

class MyClass {
public:
...
static MyClassData errorVariable;
};

....
MyClassData MyClass::errorVariable;
....

if (data are ok)
return data;
else
return errorVariable;

....
if (&returnValueFromFunction == &errorVariable)


But it's better to 'try-catch' and 'throw'.

V
 
J

Jim Langston

Dejfson said:
Dear All,
can someone clarify me how to return the reference to the empty object in
case of error?

_not working_ Example of what i'd like to do:


const MyClassData& MyClass ()
{
QListIterator<MyClassData> it(fancylist)

while (it.hasNext())
{
const MyClassData &data = it.next();

if (data are ok)
return data;
}

return MyClassData();
}



This compiles, but of course it returns invalid reference in the case when
I don't find any suitable data. It there a way how to use the reference in
such case??

I have just one solution in my mind: if I create class variable:

class MyClass {
public:
MyClass () : errorVariable() {};

private:
MyClassData errorVariable;
}


and then I modify function:


const MyClassData& MyClass ()
{
QListIterator<MyClassData> it(fancylist)

while (it.hasNext())
{
const MyClassData &data = it.next();

if (data are ok)
return data;
}

return errorVariable;
}



But I'm not sure whether I like the idea of creating additional variable
just as placeholder for something which doesn't really exist..


Is there another way?

I used throw as thus:

CPlayer& FindPlayer( const SOCKET Socket )
{
// Get a reference in the map for this player
map_player::iterator it = World.ConnectedPlayers.find( Socket );
if ( it != World.ConnectedPlayers.end() )
return (*it).second;
else
throw 0;
}

which I use a number of ways (is a client logged in, get a reference,
etc...) A few examples of usage:

// Get a reference in the map for this player
try
{
// Just do it to see if it throws
FindPlayer( Socket );
}
catch ( int )
{
SendMessageToPlayer( Socket, MSG_SERVER_MESSAGE, "<Message
not sent, please relog - Error has been logged>" );
World.MessageBuffer.push_back( LogError( "Unlogged in client
attempting to send message on socket " + jml::StrmConvert( Socket ) + " on
IP " + IP ) );
return 0;
}

===================

case MSG_REQUEST_PLAYER_INFO: // "PlayerID"
{
SOCKET PlayerID = jml::StrmConvert<SOCKET>(
StrMessage );

try
{
CPlayer& TargetPlayer = FindPlayer( PlayerID );
if ( ThisPlayer.Character.Map ==
TargetPlayer.Character.Map ) // Make sure on same map
{
SendMessageToPlayer( Socket,
MSG_CREATE_PLAYER_OBJECT, CreateCharMessage( TargetPlayer.Socket,
TargetPlayer.Character ) );
}
}
catch ( int )
{
}
}

break;

======================

case MSG_DESTROY_CLIENT:
{
try
{
CPlayer& ThisPlayer = FindPlayer( Socket );
PlayerLeft( ThisPlayer );
}
catch ( int )
{
World.MessageBuffer.push_back( "Unlogged in socket " +
jml::StrmConvert( Socket ) + " disconnected." );
}
}

break;
 
J

John Harrison

Dejfson said:
Dear All,
can someone clarify me how to return the reference to the empty object
in case of error?

_not working_ Example of what i'd like to do:


const MyClassData& MyClass ()
{
QListIterator<MyClassData> it(fancylist)

while (it.hasNext())
{
const MyClassData &data = it.next();

if (data are ok)
return data;
}

return MyClassData();
}



This compiles, but of course it returns invalid reference in the case
when I don't find any suitable data. It there a way how to use the
reference in such case??

I have just one solution in my mind: if I create class variable:

class MyClass {
public:
MyClass () : errorVariable() {};

private:
MyClassData errorVariable;
}


and then I modify function:


const MyClassData& MyClass ()
{
QListIterator<MyClassData> it(fancylist)

while (it.hasNext())
{
const MyClassData &data = it.next();

if (data are ok)
return data;
}

return errorVariable;
}



But I'm not sure whether I like the idea of creating additional variable
just as placeholder for something which doesn't really exist..


Is there another way?

thx
d.

Use a static variable inside the function

const MyClassData& MyClass ()
{
QListIterator<MyClassData> it(fancylist)

while (it.hasNext())
{
const MyClassData &data = it.next();

if (data are ok)
return data;
}

static MyClassData errorVariable;
return errorVariable;
}

This should be safe enough since you are returning a const reference.

john
 
A

asterisc

Dejfson a scris:
Dear All,
can someone clarify me how to return the reference to the empty object
in case of error?

_not working_ Example of what i'd like to do:


const MyClassData& MyClass ()
{
QListIterator<MyClassData> it(fancylist)

while (it.hasNext())
{
const MyClassData &data = it.next();

if (data are ok)
return data;
}

return MyClassData();
}



This compiles, but of course it returns invalid reference in the case
when I don't find any suitable data. It there a way how to use the
reference in such case??

I have just one solution in my mind: if I create class variable:

class MyClass {
public:
MyClass () : errorVariable() {};

private:
MyClassData errorVariable;
}


and then I modify function:


const MyClassData& MyClass ()
{
QListIterator<MyClassData> it(fancylist)

while (it.hasNext())
{
const MyClassData &data = it.next();

if (data are ok)
return data;
}

return errorVariable;
}



But I'm not sure whether I like the idea of creating additional variable
just as placeholder for something which doesn't really exist..


Is there another way?

thx
d.

Hello,

One option is to use pointers and return NULL if you can't find it in
that list.
Other option is to return as const reference parameter and return a
true/false value if found or not.

Best regards,
asterisc
 
R

RainBow

If you dont wanna have a class member like that, or dont wanna return
MyClassData() just to make it compile, how about something like this?

int MyClass (const MyClassData*& aReturnedObject)
{
QListIterator<MyClassData> it(fancylist)


while (it.hasNext())
{
const MyClassData &data = it.next();


if (data are ok)
// return data;
aReturnedObject = data;
return SUCCESS;
}


// return MyClassData();
aReturnedObject = NULL;
return NOT_FOUND;

}
 
Z

Zeppe

Jim said:
I used throw as thus:

CPlayer& FindPlayer( const SOCKET Socket )
{
// Get a reference in the map for this player
map_player::iterator it = World.ConnectedPlayers.find( Socket );
if ( it != World.ConnectedPlayers.end() )
return (*it).second;
else
throw 0;
}

Just a note, throwing 0 is a bad habit. Create a suitable exception
class, with some string that gives you the explanation of the error, and
throw that.

Regards,

Zeppe
 
Z

Zeppe

RainBow said:
If you dont wanna have a class member like that, or dont wanna return
MyClassData() just to make it compile, how about something like this?

int MyClass (const MyClassData*& aReturnedObject)

That's a C-based approach and I would avoid it. Better to return a
pointer, and only if the performances are REALLY an issue. Otherwise,
throwing is always better: it's difficult to ignore an error condition
with something is thrown :)

Regards,

Zeppe
 
R

Roland Pibinger

Your class can have a static instance of itself, something like

class MyClass {
public:
...
static MyClassData errorVariable;
};

// mutable statics are out of fashion
static const MyClassData errorVariable;
...
MyClassData MyClass::errorVariable;
...

if (data are ok)
return data;
else
return errorVariable;

...
if (&returnValueFromFunction == &errorVariable)

or a static member function:

static bool isError (const MyClassData& d);

If MyClassData becomes a friend of MyClass is needs no public funtions
or data.
But it's better to 'try-catch' and 'throw'.

Depending on the context also a Null Object
(http://www.two-sdg.demon.co.uk/curbralan/papers/europlop/NullObject.pdf)
may be used.
 
D

Dejfson

Dear All,
thanks for all these interesting responses. I'm not sure thether
try/catch is really suitable for that. Correct me if I'm wrong but
I though that this construction is used when there is really an error.
But the example what I propose should return 'nothing' if not found and
'something' if found. However, this is not an error condition. It is
working state which means simply 'searching failed, do something about
it'. For the moment I have it realized with pointers, but I try to
convert my soft into pure referencing if possible....

d.
 
D

Dejfson

Ok, I just see that when asking, I named the variable as 'error'.. This
is of course misleading. It is not error, instead 'empty' should be used



Dejfson napsal(a):
 
V

Victor Bazarov

Dejfson said:
thanks for all these interesting responses. I'm not sure thether
try/catch is really suitable for that. Correct me if I'm wrong but
I though that this construction is used when there is really an error.
But the example what I propose should return 'nothing' if not found
and 'something' if found. However, this is not an error condition. It
is working state which means simply 'searching failed, do something
about it'. For the moment I have it realized with pointers, but I try
to convert my soft into pure referencing if possible....

The best analogy with returning "nothing" I can think of is 'std::find'
that returns the 'end' iterator if nothing is found. It's not "null",
nor is it a reference. It's a value you pass in, and it serves two
purposes: to indicate the end of the sequence and to allow returing of
"not found" condition. You might want to think of passing something in
(something you would consider "nothing") so that the function could
return it if it needs to... Anyway, good luck!

V
 
D

dejfson

Hi Viktor,
this is I think exactly what i'm looking for. Have to study sources a
bit...
thanks to all
d.
 
J

James Kanze

Dejfson said:
can someone clarify me how to return the reference to the empty object
in case of error?

A reference can designate any kind of object, even an empty
collection. But more likely, what you are looking for is how to
return a reference to nothing.

The answer is, of course, that you can't. That's what pointers
(and null pointers) are for.
_not working_ Example of what i'd like to do:
const MyClassData& MyClass ()
{
QListIterator<MyClassData> it(fancylist)
while (it.hasNext())
{
const MyClassData &data = it.next();
if (data are ok)
return data;
}
return MyClassData();
}
This compiles, but of course it returns invalid reference in the case
when I don't find any suitable data. It there a way how to use the
reference in such case??

No. Is there any reason not to use a pointer?
I have just one solution in my mind: if I create class variable:
class MyClass {
public:
MyClass () : errorVariable() {};

private:
MyClassData errorVariable;
}
and then I modify function:
const MyClassData& MyClass ()
{
QListIterator<MyClassData> it(fancylist)
while (it.hasNext())
{
const MyClassData &data = it.next();
if (data are ok)
return data;
}
return errorVariable;
}
But I'm not sure whether I like the idea of creating
additional variable just as placeholder for something which
doesn't really exist..

It depends. This is a very valid solution in the case where the
reference is to a polymorphic base class; no need to test
anything, just arrange for the error class to have the desired
behavior (e.g. output an error message to std::cerr, throw an
exception, whatever). I agree that it's generally not really
indicated for value classes, however (and a name with Data in it
certainly suggests value semantics).
 
J

James Kanze


That's highly debatable. He didn't give any indication which
would make me suppose that the error condition is exceptional,
or that it could not generally be handled immediately in the
calling function. So throw looks like a bad design decision.
...
if (&returnValueFromFunction == &errorVariable)
But it's better to 'try-catch' and 'throw'.

Only if he can be relatively sure that the calling function will
not be able to process the error.
 
J

James Kanze

Just a note, throwing 0 is a bad habit.

And how. Does he expect the caller to use a "catch ( int )"?

What I'd like to know is what's wrong with simply:

CPlayer* FindPlayer( const SOCKET Socket )
{
// Get a reference in the map for this player
map_player::iterator it =
World.ConnectedPlayers.find( Socket );
return it == World.ConnectedPlayers.end()
? &it->second
: NULL ;
}

It's short and simple, and about the easiest solution to
understand.
Create a suitable exception class, with some string that gives
you the explanation of the error, and throw that.

If you have to throw. Throwing should generally be reserved for
exceptional cases.
 
J

James Kanze

That's a C-based approach and I would avoid it. Better to return a
pointer, and only if the performances are REALLY an issue.

Better to return a pointer, even in C.
Otherwise, throwing is always better:

Throwing is rarely the best solution. Only when it is certain
that the error is really exceptional, and cannot be handled in
the layer immediately above the function in the call stack, or
in a constructor, to avoid the necessity of creating the an
invalid object (and thus having to constantly test state).
it's difficult to ignore an error condition
with something is thrown :)

The Java libraries seem to do it quite well:).

It's even more difficult to ignore a well designed return code.
 
Z

Zeppe

James said:
What I'd like to know is what's wrong with simply:

CPlayer* FindPlayer( const SOCKET Socket )
{
// Get a reference in the map for this player
map_player::iterator it =
World.ConnectedPlayers.find( Socket );
return it == World.ConnectedPlayers.end()
? &it->second
: NULL ;
}

It's short and simple, and about the easiest solution to
understand.


If you have to throw. Throwing should generally be reserved for
exceptional cases.

Exactly. Exceptional given the semantic of an operation. For a function
that is called "FindPlayer" I definitely won't expect any exception to
be thrown if the player is not found. Differently, for a function like
"GetPlayer(PlayerID id)" I would usually consider the absence of that
player a good candidate for an exception to be thrown :)

Regards,

Zeppe
 

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,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top