1

When I try this:

#include <optional>                                                                         using namespace std;                                                                        
int main() {
    return make_optional(2) + make_optional(3);
}                                                                                           

I get this:

error: no match for ‘operator+’ (operand types are ‘std::optional<int>’ and
 ‘std::optional<int>’)
    5 |     return make_optional(2) + make_optional(3);
      |            ~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~
      |                         |                  |
      |                         optional<[...]>    optional<[...]>

It seems natural to add optional types same as size_t types. ~~I know Haskell supports this natively~~ (EDIT: this assumption is not entirely correct). Of course I could write a helper function. My intention of asking is to make sure there is no simpler way to do this. And before you suggest, yes I have googled, RTFM'ed, etc.

Enlico
  • 23,259
  • 6
  • 48
  • 102
sprajagopal
  • 322
  • 1
  • 4
  • 20
  • 1
    You should ask yourself if you still want to use an `optional` if you need to do math on the data type: there will be wrapping/unwrapping overhead. Anyhow: C++ is not Haskell. Completely different languages actually, different philosophy, different purposes. – JHBonarius Apr 19 '21 at 06:52
  • Why do you think this is uncommon? I can think of several instances where this is needed. Binary search for example. Anyhow, as you said, different languages. – sprajagopal Apr 19 '21 at 08:33
  • ? A binary search doesn't require arithmetic (of the elements) and arithmetic doesn't require binary search. `std:optional` is quite new in C++ (2017 standard), and it's not a zero-cost abstraction. `Boost::Optional` is older (2003?). Before that people seemed to be happy just check the result from a `std::find` (=binary search) and execute code based on that. No common need to remember the 'optionality' of a value and transport that all around. (Or sometimes a pointer with nullptr would be used, to indicate it doesn't have a value). C++ is used for other purposes. – JHBonarius Apr 19 '21 at 09:33
  • I think you misunderstood. Binary search (or any search for that matter) may or may not return a valid index. Implemented recursively and with optional, this would involve adding. Anyway, the rest of your comment is probably valid. I don't know much about the history. – sprajagopal Apr 19 '21 at 10:13
  • @sprajagopal: "*Implemented recursively and with optional, this would involve adding.*" That's one way to implement it, but not the only way. C++'s binary searching uses iterators, not indices. And it was implemented in C++98 without any need for optional. – Nicol Bolas Apr 19 '21 at 13:49
  • @JHBonarius: It's true that there is _some_ unwrapping, but this is C++. `std::optional` guarantees that any contained `T` object is stored as a subobject of the `optional`, i.e. it does not use the heap. If the `optional` is on the stack and contains a T, then that T also lives on the stack. Unwrapping the T is just a pointer offset, and that offset could be zero. But even for non-zero offsets, modern CPU's can handle constant offsets for zero cost at load time. – MSalters Apr 19 '21 at 13:59
  • @MSalters yes, but is slightly bigger. So for small trivial types, especially when stored in arrays, you can have less of them on the stack. Plus more likely to run into a cache miss. I'm not saying that optional is bad whatsoever. It's just not a one-size-fits-all. – JHBonarius Apr 19 '21 at 16:47
  • @NicolBolas, umm, I think we are talking across each other. The discussion seems to be more history related. Regardless I hope others find the info valuable. Thanks again for your inputs – sprajagopal Apr 19 '21 at 17:19

1 Answers1

1

As you can see here std::optional simply doesn't offer an operator+ member. After all, std::optional is able to contain anything, including types for which operator+ doesn't make sense. What would optional<that_type>::operator+ do for those types?

Clearly, you can write your own free function (modulo const/&/both or whatever you deem appropriate for parameters/return type):

std::optional<int> operator+(std::optional<int> o1, std::optional<int> o2) {
    if (o1) {
        if (o2) {
            return std::make_optional(o1.value() + o2.value());
        }
    }
    return std::nullopt;
}
Enlico
  • 23,259
  • 6
  • 48
  • 102
  • Is there a design choice here? I assumed `Maybe` in Haskell is equivalent to `optional` in C++. But is that a valid assumption (apart from the available operators)? – sprajagopal Apr 19 '21 at 06:27
  • 3
    @sprajagopal, in Haskell `Just 1 + Just 3` is invalid. – Enlico Apr 19 '21 at 06:30
  • 2
    I don't understand the logic here. `operator+(std::optional, std::optional)` could simply `require` that a suitable `+` exists: `requires requires (T t, U u) { t+u;}`. The return type would be `std::optional>`. That seems reasonable enough, so why the question in the first paragraph? – MSalters Apr 19 '21 at 13:49
  • 1
    Note BTW that this `operator+` is not defined in `namespace std`, which means it will not be found by Argument Dependent Lookup on `std::optional`. This is unavoidable; it's not your namespace. – MSalters Apr 19 '21 at 13:53
  • @MSalters, isn't `require` a C++20 keyword? If you refer to checking that the input satisfies a concept (one could do it with a `static_assert` or via SFINAE, I believe), yes, it could be done, but given the meaning that the name of `std::optional` implies, imho it's not obvious that it should take care of facts that are specific to the one or the other type that you might put in it. – Enlico Apr 19 '21 at 13:59
  • As regards your second comment, I guess the user of the code should just acknowledge what you noted and not rely on ADL. – Enlico Apr 19 '21 at 14:00
  • @Enlico: True, for C++17 you could do it the old-fashioned way with `std::enable_if`, or just rely on direct SFINAE due to the lack of a `common_type`. C++20 `requires` is useful to get more readable errors. – MSalters Apr 19 '21 at 14:01