0

I have a function that solves one of 4 kinematic equations. The parameters are floats, and Is there a way to distinguish between a NULL parameter and a parameter with a value of 0. I've read up on the subject and it seems that NULL and 0 are the same. The reason I want to distinguish a 0 from a form of "nothingness" is because a 0 value assigns a value and "nothingness" shows that we don't know what that value is.

float doSomething(float& foo, float& bar, float& goo, float& baz){
    if(foo == (insert_null_value_here)){
        return (foo_after_we_did_some_equation);
    }
}

The "null" value can't be NULL or 0 as I already discussed. If the parameters were all pointers to floats, would this work if I checked for "nullptrs"?(Not my main question) Even if the former question is yes, what value can I use for non-pointer/reference types?(Re-statement of main question)

Orange Mushroom
  • 431
  • 4
  • 16

2 Answers2

6

There is no such thing as "a null parameter". Those references cannot compliantly "be null".

(It's important not to conflate this with the idea of a null pointer, which used to have value zero for legacy reasons — with a macro NULL defined to be zero for "convenience" — but nowadays is nullptr.)

If you want to make those values optional, use boost::optional, which forms a wrapper around a data member and a boolean indicating whether the member is populated:

float doSomething(boost::optional<float>& foo)
{
   if (foo) {
      return someEquation(foo.get());
   }

   return somethingElse();
}

Now, valid values are:

  • 3.5f
  • 42
  • 0
  • -5

And to pass no value at all:

  • boost::none

If you want to keep the ref-to-non-const, you'd do something like:

boost::optional<float> myValue = 3;  // or 42, or 5.1, or boost::none
doSomething(myValue);

boost::optional was nearly std::optional as of C++14, but is now part of the Library Fundamentals TS that we hope will make it, in entirety, into C++17.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • *"boost::optional was nearly std::optional"*... this seems to be the case very often, look at ``. `boost` seems to be the `C++` beta playground. (Note this comment has nothing to do with your post, it just got me on a side rant) – Cory Kramer Dec 29 '14 at 19:46
  • 1
    @Cyber: Boost is absolutely the C++ standard library playground. :) – Lightness Races in Orbit Dec 29 '14 at 19:47
  • And if foo = 0, it wont be considered false? Only if boost::none is the actual parameter? – Orange Mushroom Dec 29 '14 at 19:49
  • @anoyd_bi_me_grammers: Correct. – Lightness Races in Orbit Dec 29 '14 at 19:49
  • Hmm, I was expecting if(0){} to not work since 0 is false when converted. – Orange Mushroom Dec 29 '14 at 19:51
  • @anoyd_bi_me_grammers `if (foo)` where `foo` is a `boost::optional` object only checks to see if the optional object *has a value*. It doesn't actually *look at the value itself*. – cdhowie Dec 29 '14 at 19:51
  • 1
    Maybe just make `doSomething` take an `optional` by-value? Answer reads a little confusingly otherwise, even with your caveat at the end. – Barry Dec 29 '14 at 19:52
  • @anoyd_bi_me_grammers: But the code does not do that. Foo is in fact never `= 0` ... it is an object that potentially wraps the value `0`. It has its own conversions that are designed to run this test properly for you. That's the entire point! Notice how I had to write `foo.get()` to actually get the underlying `float` value. – Lightness Races in Orbit Dec 29 '14 at 19:52
  • 1
    @Barry: The OP's code takes a `float` by reference and I assume there's actually a reason for that. – Lightness Races in Orbit Dec 29 '14 at 19:53
5

Adding my 2 cents here.

You could also use pointers directly, and send nullptr for parameters that you do not want to send values for. This is, in case you do not want to include Boost for a minor feature.

Also you cannot check references for nullptr. They are supposed to have a proper address by default.

Swtsvn
  • 315
  • 2
  • 13
  • 1
    References do not have addresses. – Lightness Races in Orbit Dec 29 '14 at 19:54
  • I'd have to say that Boost is very useful, but not for such a minor feature, and I want the ability to change the float values with simplicity. – Orange Mushroom Dec 29 '14 at 20:08
  • @LightnessRacesinOrbit the address-of operator `&` works on them just the same. – Mark Ransom Dec 29 '14 at 20:12
  • 1
    @MarkRansom: No, the address-of operator is applied to the referent. `[C++11: 8.3.2/5]` states: _"**There shall be** no references to references, no arrays of references, and **no pointers to references**._" You cannot take the address of a reference. It is simply impossible. A notion for which the language does not provide. References, as distinct from pointers, are aliases rather than "objects" in their own right (though this abstraction does sadly yet unavoidably leak in a couple of places, such as storing references as data members). – Lightness Races in Orbit Dec 29 '14 at 20:16
  • @LightnessRacesinOrbit indeed it is, which is why one might be tempted to use it to see if the referent is a dereferenced null pointer. Except of course that dereferencing a null pointer leads to undefined behavior, see my comment on the question for an example. – Mark Ransom Dec 29 '14 at 20:22
  • 1
    @MarkRansom: Right - as I said in my answer 45 minutes ago, references cannot compliantly "be null". You've invoked UB and it's too late. I don't really follow what you're trying to say at this point! – Lightness Races in Orbit Dec 29 '14 at 20:25
  • @LightnessRacesinOrbit it seemed that you were arguing the final point in this answer, not just mentioning a technicality. I commented not necessarily for your benefit but to clarify the issue for other readers. – Mark Ransom Dec 29 '14 at 20:29