lamarrr/STX

Option<T&> specialization

NathanSWard opened this issue · 2 comments

Is your feature request related to a problem? Please describe.
I absolutely love using the STX library. However, I always run into a problem when I want to return an optional reference to something, and do not have the provided facilities. For example, I have a map class map<int, ExpensiveType>. I want to have my lookup function return a reference to the value if the key exists, and None if the key does not exist. Being able to return stx::Option<ExpensiveType&> would allow me to maintain my functional programming approach to my code instead of returning a raw pointer or throw exception, etc...

Describe the solution you'd like
Create a template specialization for stx::Option<T&> that under that hood only holds a pointer to the T.
I would strongly argue that stx::Option<T&> should not be re-assignable into order to mimic reference semantics and this avoids the debate on weather the assignment operator should assign through to the T. Also, the interface of Option<T&> would be limited when compared to the non-reference version. E.g. replace and unwrap_or_default would not be available for the Option<T&> interface.

Describe alternatives you've considered
The only other option to achieve the following is stx::Option<stx::Ref<T>> however, this is not optimal as you can represent the Option reference as just a pointer instead of a reference wrapper and a bool.

Additional context
I have a branch of STX where I implement the Option<T&> specialization and would gladly create a PR in the case this feature is considered a good idea to add.
Note: I would also consider extending this to include Result<T&, E>, Result<T, E&>, and Result<T&, E&> specialization. However, as of right now, I believe Option<T&> has many more use cases and is quite practical/trivial to implement.

Thanks, Nathan!
I've been considering adding it. But I've been holding back cos I didn't feel a specialization would be a good idea, considering the number of methods it has. Duplicating these methods will be error-prone. I'd argue that the semantics should be rebind.
Nonetheless, I'd love to see your PR and will be happy to take a look into it and consider it.
Also, in the case of the pointer representation, I'd recommend a pointer and a bool, or std::reference_wrapper and a bool. Considering that nullptr dereference is UB, meaning that we can't predict what behaviour would occur on all systems, assuming a system decides to proceed in this scenario, and an Option<T&> tries to bind to the result of such dereferencing, the address of the l-value ref will be nullptr, which we'll also be using as a sentinel value. It is in fact error-prone for the general-purpose use-case (I might be wrong).
This is a part of the sentinel-based code we're trying to avoid with the Option and Result monadic types.

I'll be closing this as stale