Skip to content

What should moving from optional<T&> into optional<T> do? #92

@jiixyj

Description

@jiixyj

I'm wondering about the interactions between optional<T&> and optional<T>. Specifically about optional<T>'s "converting" move constructor when the RHS is a optional<T&>. Should there be a move from the "remote" value, or should the value category be shallow, leading to a copy? Example:

    {
        std::string s = "qwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnm";
        beman::optional26::optional<std::string&> o1 = s;
        beman::optional26::optional<std::string> o2 = std::move(o1);
        EXPECT_???(s.empty());
    }

At the moment, there is a move happening, and s is empty. I'm not sure if this is intended behavior though, or a "happy accident".

In any case, the "converting" move constructor of optional<T> seems not yet aware of optional<T&>:

/// Converting move constructor.
template <class T>
template <class U>
inline constexpr optional<T>::optional(optional<U>&& rhs)
    requires detail::enable_from_other<T, U, U&&> && std::is_convertible_v<U&&, T>
{
    if (rhs.has_value()) {
        construct(std::move(*rhs));
    }
}

...if U is a reference here, the U&&'s collapse to simple references. So detail::enable_from_other actually checks if it can copy the value of the rhs in the constraints, but then does a move inside the function body.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions