4

I have a function with the following header:

std::vector<NxU32> MySewer::createCuttingArray(MyCloth** cloth, NxU32 startPoint, NxU32 endPoint)

The function is supposed to return a vector containing some integer values. But there is one problem: If the line is not correctly created (there is a way in which this can happen), I want to do something like what I did in Java and C#, to return a NULL. But from what I see, in C++, NULL is defined as an integer value. How can I return a valid NULL for a vector?

user2399378
  • 829
  • 2
  • 10
  • 23
  • 13
    Throw an exception instead? – syam May 30 '13 at 15:12
  • 3
    you could return a pointer. – Daniel A. White May 30 '13 at 15:12
  • 3
    You can also return an empty vector... and deal with it just as you would deal with NULL - Edit: Double ninjas... – i Code 4 Food May 30 '13 at 15:14
  • 2
    You can return an empty vector. – selalerer May 30 '13 at 15:14
  • 1
    Three times the same answer within seconds :D – SinisterMJ May 30 '13 at 15:14
  • 2
    You might want to look into the "Optional" class in boost. http://www.boost.org/doc/libs/1_53_0/libs/optional/doc/html/index.html I think that std::optional is planned for c++14 which doesn't help you now. – jcoder May 30 '13 at 15:16
  • Another way to handle this is to return an error code (int), and instead pass in a reference to the vector, which is generally better because returning a vector like you are doing will force a copy. E.g.: int MySewer::createCuttingArray(std::vector & values, MyCloth** cloth, NxU32 startPoint, NxU32 endPoint) – Blazes May 30 '13 at 15:18
  • I provided an answer below, but see also related questions http://stackoverflow.com/q/10371094/96780 and http://stackoverflow.com/q/7425241/96780. – Daniel Daranas May 30 '13 at 15:23

7 Answers7

11

The "correct" way to deal with this really depends on what the code receiving the vector actually does. Is it cause for an error, or simply "we ignore this"?

If it's an error, use throw some_exception_goes_here;, because that is much easier than going down the line with a NULL value.

If you want to just ignore it, return an empty vector and then make sure the code below isn't going to have problems with an empty vector.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
7

By your description, what you want is boost::optional<std::vector<NxU32>>.

I hope the name makes its intent obvious.

http://www.boost.org/doc/libs/release/libs/optional/doc/html/index.html

Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
  • 2
    Or `std::optional`, in the (hopefully) not too distant future. – juanchopanza May 30 '13 at 15:17
  • I like this if you're using boost already so +1. Just be careful to write boost::optional > (note the space between the > >) if your compiler does not support >>. – Bathsheba May 30 '13 at 15:23
1

boost::optional<T> addresses this problem by extending a type T to be a type that can either "have a value of type T" or "not have a value." In your case, you would be returning a boost::optional<std::vector<NxU32>> because you want to, in some cases, return "nothing."

The boost documentation has some examples here.

This functionality seems basic enough that you might expect it to be part of the standard library. Sadly, it isn't (yet). See related: boost::optional alternative in C++ Standard Library

Community
  • 1
  • 1
Timothy Shields
  • 75,459
  • 18
  • 120
  • 173
1

I don't think there is a need for any boost::optional nor std::exception. What you should return is an empty vector. Think about it. The function returns a list of integers and the function caller operates on the list of integers. If the list is empty, then there is nothing to operator on. For example( in psuedo)

std::vector<T> data = createData(args);
for(int i = 0; i < data.size(); ++i){
      calculate(data[i]);
}

That for loop isn't going to execute if the data is empty. There is no need for null checks or exception handling.

dchhetri
  • 6,926
  • 4
  • 43
  • 56
0

You can't. To emulate the behaviour of reference types in .NET, of which variables can be either attached to an actual object or be null, you need to use pointers in C++. Pointers can be either NULL or point to a valid object.

Daniel Daranas
  • 22,454
  • 9
  • 63
  • 116
0

On balance, I think I'd change the pattern. Create the vector in the caller, pass as a reference (or pointer) into your function and have a bool return true / false indicating success or failure.

Doing it this way also means you're not invoking the std::vector<> copy constructor on the return value.

If you already have boost installed and up and running I'd be tempted to return boost::optional as other answers indicate. But note that getting boost to work can be a headache, (it has its own build environment which is a learning curve) especially if you're using StlPort.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • That's a bad interface (although it was a good/preferred choice before C++11) because there is nothing forcing client code to check the return value (client may assume the vector was populated) and because any complete client implementation will be forced to use an if on the result). – utnapistim May 30 '13 at 15:29
  • Out of interest, what would you do in C++11? – Bathsheba May 30 '13 at 15:43
  • If the error is ignorable, return an empty vector; If the error is not ignorable, throw an exception. Client code will just get the result and process it (and exceptions will be handled wherever client code handles errors). – utnapistim May 30 '13 at 15:53
-2

You just can't do that in C++.

You are returning a vector that will be copied (and instantiated among other things). Other thing is that you can't cast something that isn't a vector to NULL.

André Moreira
  • 1,669
  • 4
  • 21
  • 35
  • -1. You do not _know_ that it will be _copied_. The copy can be [elided](http://en.wikipedia.org/wiki/Copy_elision) during optimization (RVO/NRVO) or the poster may use C++11 move semantics with [`std::move()`](http://en.cppreference.com/w/cpp/algorithm/move) – Captain Obvlious May 30 '13 at 15:51
  • @CaptainObvlious, well we are always learning new stuff :). Nevertheless in standard C++ you just can't return two types. – André Moreira May 31 '13 at 12:06
  • When I downvoted I was cranky, sorry. The point I **should** have made is that your answer is too absolute given that it isn't accurate. Another key point is that just because the language itself does not _directly_ support something doesn't mean there isn't another way to accomplish it. For instance if I wanted to return _two_ values I might return a `std::pair<>` instead. It's still technically returning a single value but the pair itself contains two values and would satisfy the requirements of a needed solution. – Captain Obvlious May 31 '13 at 14:10
  • FWIW, if you get another downvote you can delete the answer and get a peer pressure badge ;) – Captain Obvlious May 31 '13 at 14:11
  • @CaptainObvlious You are right, it was an absolute answer :). As you point out, there are other ways that are supported by the standard ;) – André Moreira May 31 '13 at 15:51