C++: Return NULL instead of struct
Asked Answered
N

8

10

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.

Nacred answered 15/6, 2010 at 23:34 Comment(2)
Your return type is inconsistent. If the search succeeds, it is Foo&; if it fails, it is ErrorCode. A solution to this problem would be to return a Foo*, which points to the element that was found, or is NULL if no element was found.Uglify
Related, maybe duplicate: Nullable values in C++Sen
C
14

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.

Clarethaclaretta answered 15/6, 2010 at 23:40 Comment(4)
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).Peipeiffer
@Martin: I'll just say that's a more generalized pointer and meet you half-way. :PClarethaclaretta
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.Crenelate
I think doing C++ by applying knowledge from other languages is excellent; it will improve C++ to become more modern in the end.Reisman
M
3

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

Martens answered 15/6, 2010 at 23:45 Comment(0)
K
3

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.

Kohlrabi answered 15/6, 2010 at 23:53 Comment(0)
B
2

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.

Bethezel answered 15/6, 2010 at 23:36 Comment(3)
fooFound is just the condition to check, fooResult is what's returned.Bethezel
Another possibility is boost::optional<Foo>. Then you don't have to remember to delete it.Jerriejerrilee
@Mike Seymour: Thanks - nabbing that to complete my answer #3Malfunction
J
0

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

Justice answered 15/6, 2010 at 23:35 Comment(1)
@Dura, the question is "How can I accomplish this in C++?"Justice
N
0

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;
}
Nf answered 15/6, 2010 at 23:41 Comment(3)
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.Alas
@Billy: Easy on the -1s. struct means value type, not reference and you can do a nullable value type - that's the whole pointMalfunction
+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.Malfunction
G
0

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.

Gamache answered 16/6, 2010 at 15:12 Comment(1)
That would be my approach. Keeping things simple, and dependencies minimal.Flyer
M
-1

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
Malfunction answered 15/6, 2010 at 23:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.