Is there a compact way to make std::optional<T>::value_or work on member variables of T

Viewed 214

Consider the following code:

#include <iostream>
#include <optional>
struct S{
    int b;
    int e;
};

void fn(const std::optional<S>& maybe_s){
    int begin = maybe_s? maybe_s-> b: 0;
    int end = maybe_s? maybe_s->e : 100;
    std::cout << begin << "    " << end << std::endl;
}

int main() {
    std::optional<S> empty_opt;
    fn(empty_opt);
    std::optional<S> active_opt{S{11, 47}};
    fn(active_opt);
}

Here I want something like value_or but not for S, but for it's members. Is there a way to do this nicely in C++?

Note that I want this to work in class initializer list, so I cant use structured bindings.

I have this solution, but I prefer to use something from std:: if possible(ease of reading for new developers, also my solution probably has performance problems + no proper constraints, e.g. that V must be convertible to result of invoke...).

template<typename T, typename M, typename V>
decltype(auto) memb_or(const std::optional<T>& opt, M m, const V& default_val){
    if (opt){
        return std::invoke(m, *opt);
    } else {
        return default_val;
    }
}
1 Answers

Whilst not yet in the standard, P0798R6 (Monadic operations for std::optional) may be offering some sugar for what you're looking for, which is implemented in Sy Brand's std::optional implementation.

It looks as if the proposal was just recently approved for C++23:

JeffGarland commented on Jul 10

LWG completed review 2021-07-09

poll: Adopt D0798R8 Monadic operations for std::optional for C++23?

F  A  N
7  0  0
Related