What's the point of ref-qualified member functions in `std::optional::value`

66 Views Asked by At

These are the signatures, according to Cppreference:

constexpr T& value() &;
constexpr const T& value() const &;

constexpr T&& value() &&;
constexpr const T&& value() const &&;

What's the point of using &/const& and &&/const&&? Especially, I don't understand the point of having a const&& overload. const objects shouldn't be moved, so why would we have this?

1

There are 1 best solutions below

2
On BEST ANSWER

It's all about being in a generic template context. The standard library here needs to support all the possible scenarios (you an imagine and the ones you can't imagine) because I assure you some C++ project somewhere does use it.

So if you have a user defined type X as follows:

struct X
{
    void foo() &;          // 1
    void foo() const &;    // 2

    void foo() &&;         // 3
    void foo() const &&;   // 4
};

where foo is optimized for const temporary (foo (4)) vs const non-temporary (foo (2)) the standard library needs to support that with std::optional.

If std::optinal would be missing the constexpr const T&& value() const &&; when the user has a std::optional<X> const && (it can be in a generic template context) and tries to call foo on it the foo (2) would be called instead of foo (4).

What I mean by calling foo here:

const std::optional<X> && get_const_xvalue();
get_const_xvalue().get()foo();

// or in a generic template:

template <class Opt>
void bar(Opt&& o)
{
    std::forward<Opt>(o).get().foo();
}

// where `o` can be of type `std::optional<X> const &&`

There is a worst scenario. Imagine a user type type Y like so:

struct X
{
    void foo() &       = delete;  // 1
    void foo() const & = delete;  // 2

    void foo() &&;                // 3
    void foo() const &&;          // 4
};

In this case trying to access foo on a const temporary would result in a compiler error instead of calling the expected foo 4 overload.