0

I have a function that returns a pointer to an object of type bool for a given name. If the object is not found, nullptr is returned.

Now I would like to set a variable to the value of the returned boolean or false if not found. Can I write it like this?

bool flag = *Get("name");

Is this equivalent to this longer implementation?

bool *result = Get("name");
bool flag = result == nullptr ? false : *result;
danijar
  • 32,406
  • 45
  • 166
  • 297
  • 1
    You'd be better off overloading with a `bool Get(const char* identifier, bool if_missing)` function (or `get_with_default(...)` if you prefer), so you can say `bool flag = Get("name", false);`. Many interfaces use this approach. – Tony Delroy Feb 27 '14 at 11:02
  • @TonyD This sounds very interesting. Unfortunately, the get function actually is templatized like `Get(std::string Key)` and thus, proving a fallback is not that easy for all types. For types without default constructor, I couldn't default it like `T *Fallback = new T()`. – danijar Feb 27 '14 at 11:11
  • @danijar: that can still work. Consider the `vector::resize` function in C++03 (it changed in C++11). It has a default argument that uses the default constructor. If the type doesn't have a default constructor then the function still compiles but the caller *must* provide the argument. – Steve Jessop Feb 27 '14 at 11:15
  • @danijar: `template T Get(const char* identifier, const T& if_missing) { T* p = Get(identifier); return p ? *p : if_missing; }`... no? You don't need a default constructor - you can let the caller specify the fallback value they want as the second `if_missing` argument (though sometimes it's nice to offer a default-constructed default value for that argument). (This was going through my mind when I suggested overloading "Get" where the `if_missing` was mandatory to ensure the new behaviour, versus a `get_with_default` where you could provide a defaulted 2nd argument). – Tony Delroy Feb 27 '14 at 11:18
  • @TonyD This would make the interface more complex, that's why I won't use this approach here. But thanks for telling me the interesting concept though. – danijar Feb 27 '14 at 12:52

5 Answers5

2

No it's not equivalent. In the first case, if your method returns nullptr, you'll probably get runtime error.

Ashalynd
  • 12,363
  • 2
  • 34
  • 37
2

This is not equivalent. In the first case you are trying to dereference nullptr which will crash while in the second you do a proper check first.

filmor
  • 30,840
  • 6
  • 50
  • 48
2

If I understand correctly, you want something that can be nullptr, true or false.

The boost libraries (www.boost.org) have an optional class which you could exploit:

boost::optional<bool> foo;

This allows you to check for nullness using if (!foo), and if the converse is true then you use * to recover the boolean value.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • In many ways yes (reduces the overhead of a heavyweight 3rd party library). But boost::optional does allow you to treat `foo` as a variable in itself. – Bathsheba Feb 27 '14 at 11:02
2

The first is not correct since you cannot dereference a null pointer.

The second is correct but simplifies to:

bool flag = result && *result;

If you want to avoid the result variable for each call then do it like:

bool istrue(bool const *result) {
    return result && *result;
}

bool flag = istrue(Get("name"));
Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
1

The two are not equivalent. The first implementation will cause a segmentation fault (as you will be attempting to dereference a NULL pointer).

The second alternative is correct.

utnapistim
  • 26,809
  • 3
  • 46
  • 82
  • Ahh thanks, I haven't seen this. Is there another way to accomplish the desired behavior without using a helper `result` variable? – danijar Feb 27 '14 at 10:45
  • @danijar: If you can't modify the interface of `Get` but you want to avoid a `result` variable then either call `Get` twice or else write a function and pass the result of `Get` into it. – Steve Jessop Feb 27 '14 at 11:07
  • @SteveJessop I decided to go with the second option. – danijar Feb 27 '14 at 11:08