views:

311

answers:

8

I have a struct Foo. In pseudocode:

def FindFoo:
   foo = results of search
   foundFoo = true if a valid foo has been found  

   return foo if foundFoo else someErrorCode

How can I accomplish this in C++?

Edited to remove numerous inaccuracies.

+1  A: 

That doesn't work in C# either. You should return a pointer to Foo.

Matthew Flaschen
@Dura, the question is "How can I accomplish this in C++?"
Matthew Flaschen
It has a C# tag too!
nevets1219
A: 

You cant do this in C# either - you would need to return new Foo(), not null to make the compiler happy.

Ditto the C++ case - you need to instantiate a struct if you're going to return by value. If not, you want to return by pointer (in which case you'd be newing or returning a pointer to one allocated in another manner, which brings messy ownership transfer semantics into the equation).

EDIT: Based on your update. It seems you want to return either a value or a 'null' meta-value that indicates 'not found'. You can do this in a number of ways:

  1. throw if it fails, otherwise unconditionally return a value
  2. return a pointer - but this leaves the responsibility for deleting it up in the air if it's not something that's going to stay in memory long term
  3. wrap it in a [templated] wrapper object that handles the conditionality in the same way that .NET's Nullable<T> would (I'll let someone chime in with the right one UPDATE: @Mike Seymour says it's boost::optional<foo>)
  4. use the Null Object pattern to return an appropriate value which does the right thing when treated as a valid resut on the client side
Ruben Bartelink
A: 

One way of doing it is to return a pointer to a foo:

public Foo* findFoo()
{
    return fooFound ? new fooResult() : NULL;
}

Another possibility to define a NullFoo of some kind, possibly as a struct extending Foo with an empty implementation. For more information about the latter idea, you can read about the Null Object Pattern.

Edit: The modified question is somewhat different, and as other people have mentioned, you may be best off throwing an exception rather than doing either of the above.

Justin Ardini
fooFound is just the condition to check, fooResult is what's returned.
Justin Ardini
Another possibility is `boost::optional<Foo>`. Then you don't have to remember to delete it.
Mike Seymour
@Mike Seymour: Thanks - nabbing that to complete my answer #3
Ruben Bartelink
+10  A: 

C++ objects can never be null or empty. Pointers can hold a null pointer value indicating they point at nothing.

The typical solution would be to throw an exception. Otherwise, use a pointer; just make sure you aren't returning the address of a temporary.

I wouldn't recommend trying to teach yourself C++ with knowledge from other languages, you'll hurt yourself. Grab a good beginner-level book, it's the best way to learn.

GMan
+1 for "I wouldn't recommend trying to teach yourself C++ with knowledge from other languages"
Billy ONeal
@Billy yeah I gotta +1 for that too haha.
Rosarch
I think the typical solution would be to mimik the STL which returns an iterator like object that point to invalid objects (one past the end of the container).
Martin York
@Martin: I'll just say that's a more generalized pointer and meet you half-way. :P
GMan
Returning an iterator-like object only makes sense if you're creating a container that you want to be able to iterate over. Where a `find` function is involved, that's potentially the case, but not necessarily.
Tyler McHenry
+1  A: 

It's not possible in C++ without resorting to pointers or a library solution outside the standard library. (Boost is not a part of the standard library, it's a 3rd party solution.)

In C#, you can use a Nullable<Foo>.

Contrary to Billy's comment, structs are value types, not reference types, and Nullable can be applied to any value type, not just built-ins. The following compiles just fine:

struct Test {
    int Blah;
}
void Main() {
    System.Nullable<Test> proof;
}
zildjohn01
@zildjohn01: No, you can't. First of all, Nullable is only valid on the internal types, not on user defined types like `Foo`. Second, even if it were valid, it'd not help you anyway because object references can already be null. And finally, the OP asked to return an error code, not NULL.
Billy ONeal
@Billy: Easy on the -1s. struct means value type, not reference and you can do a nullable value type - that's the whole point
Ruben Bartelink
+1 factually correct re the .NET bit. Ditto the C++ bit, though omits ways around dropping to pointers [such as Null Object pattern, throwing, wrapping in a boost::optional]. +1ing as answer not off topic or incorrect. Far more irellevant and incomplete answers have been upvoted here.
Ruben Bartelink
-1 wrong on C++. The direct equivalent of `Nullable<Foo>` is `boost::optional<Foo>`
MSalters
+3  A: 

Throw an exception. That's what they're for.

DeadMG
+3  A: 

You can look into boost::optional and see if it fits your needs. However:

return foo if foundFoo else someErrorCode

This makes me think that you might be better off throwing an exception if you don't find foo.

FredOverflow
A: 

Is not finding a foo really an exceptional situation? Then throw an exception. Expect to not find foo? have the function return an error code and pass the foo out via a reference parameter, where foo is only valid if the function returns no error.

stonemetal