1

I need nullable double and int. In C# I can use double? and int?, in C++ it seems we only have boost::optional. However it seems boost:optional doesn't support many things "out of the box", for example I can't easily devide variables

That's why I'm asking if this is a good idea at all to use boost::optional in such simple case? I'm writing latency critical code so I'm choosing technologies thoroughly.

If boost::optional<double> comparing to raw double + boolean will be:

  • signifficantly slower?
  • error-phrone?
  • less readable and mainanable?
  • other problems?

upd i realized that i can just use double + isnan(). i can use nan instead of addition bool field.

Community
  • 1
  • 1
Oleg Vazhnev
  • 23,239
  • 54
  • 171
  • 305
  • Yes, `double+boolean` is probably slower, more error prone, less readable, and has other problems compared to `boost::optional` – Mooing Duck Apr 23 '14 at 18:49
  • 2
    @MooingDuck I'd be interested to see the proof you have that "double+boolean" is, in general, slower – sehe Apr 23 '14 at 18:51
  • Is there a reason that you can't just use a double* or int*? More context would help to see if you are over thinking the problem. – Velox Apr 23 '14 at 19:07
  • This can be used to call arbitrary functions with `optional` parameters, and it returns `empty` if any parameters are `empty`: http://coliru.stacked-crooked.com/a/4e44f6a756a3170f – Mooing Duck Apr 23 '14 at 19:10
  • you cannot represent `nan` anymore if you use `nan` to represent `none` – sehe Apr 23 '14 at 19:10
  • @Velox i never thought about `double*` but it's also an option, however i think `double + isnan` must be faster cause i don't need extra space to store pointer – Oleg Vazhnev Apr 23 '14 at 19:11
  • @sehe well i don't need to distinguish between `none` and `nan`. I only care if value exist or not. – Oleg Vazhnev Apr 23 '14 at 19:12

2 Answers2

3

You choose. Using T + bool is:

  • signifficantly slower?

    • not necessarily. In fact, in rare instances things could be slower with optional. It all depends on the memory layout and access patterns, so there is not much other than the usual profile, profile, profile mantra.
  • error-phrone?

    • yes it is objectively more error prone, because it is much easier to forget to check the bool, or to forget to update the bool on reset
  • less readable and mainanable?

    • yes it is less readable because the typename doesn't make the intent clear
    • yes it is less maintainable because changing/moving/renaming the variable requires modifying two variables instead of one.
      Example: Replacing optional<T> with e.g. unique_ptr<T> (or even T*) is trivial (because the null/none-checks use the same syntax), however, replacing bool+T is not a simple subsitution exercise.
  • other problems?

    • Optimization. optional could well be optimized for T's that don't use all capacity
    • conversely, std::vector<bool> + std::vector<T> could well be more efficient (storage wise) than std::vector<optional<T>>; the runtime would likely be slower, depending on usage patterns as always. (profile, profile, profile)

TL;DR: Correctness first, optimize later.

If you want lifted arithmetic operations, just strong-typedef the optional and overload operators for it.

sehe
  • 374,641
  • 47
  • 450
  • 633
2

boost::optional would be the normal approach I would take in C++.

It seems safe to say that compared to double+bool boost::optional should be less error-prone and more readable. As for performance the only way to know for sure is to profile both ways in your use-case and see which is faster. Keep in mind that boost::optional supports in-place construction and I do suspect has very little overhead for the functionality it provides.

And briefly addressing your comment about division, C++ is a strongly typed language and doesn't allow implicit conversions from one type to another in many cases. You need to tell the language what your intention is, which has the added advantage of allowing you to write clearer code, possibly even increasing its robustness.

Mark B
  • 95,107
  • 10
  • 109
  • 188