2

I'm trying to return a std::optional to an object containing a std::unique_ptr member. However, when I try to change the optional return type to use a reference, I get errors like this:

error: cannot bind non-const lvalue reference of type std::optional<ObjectWithConnection>& to an rvalue of type std::optional<ObjectWithConnection>

Is this the best way to return _aConnection without encountering any copying/latency across the stack frames?

I use references very often, but I've never used std::optional with std::unique_ptr and I'm concerned what it's doing under the hood.

struct ObjectWithConnection
{
    std::unique_ptr<Connection> _aConnection;
};

struct ConnectionsContainer
{
    // If I change return type to reference, get compiler error
    std::optional<ObjectWithConnection> getConnection(const std::string& key)
    {
        auto iter = _connections.find(key);
        if(iter != _connections.end())
        {
            return std::optional<ObjectWithConnection>(std::move(iter->second));
        }

        return std::nullopt;
    }

    std::unordered_map<std::string, ObjectWithConnection> _connections;
}

struct AnotherClass
{
    // If I change return type to reference, get compiler error
    std::optional<ObjectWithConnection> getConnection(const std::string& key)
    {
        return _container.getConnection(key);
    }

    ConnectionsContainer _container;
};
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
bcguy
  • 21
  • 3
  • 5
    `return std::optional(std::move(iter->second));` returns a temporary `std::optional`. If you declare the return type as a reference you will return a dangling reference as the temporary `std::optional` which has been destroyed. – Richard Critten May 11 '22 at 16:21
  • 3
    But, just in case: what exactly does "change the optional return type to use a reference" mean? When asking about code that doesn't work, it's more helpful to show the actual code that doesn't work, instead of different code that does work. – Sam Varshavchik May 11 '22 at 16:23
  • 4
    A function named `get` should probably not be changing the container. If you `std::move` an object of `_connections` when you `getConnection` means you can only ever `getConnection` up to once per `key`. The next time you try the `ObjectWithConnection` will already have been moved out. Unless the goal is for `get` to transfer ownership entirely, consider just returning a `ObjectWithConnection*` instead. – François Andrieux May 11 '22 at 16:23

1 Answers1

-1

There are no std::optional references. A program is ill-formed if it instantiates an optional with a reference type. Alternatively, an optional of a std::reference_wrapper of type T may be used to hold a reference.

73v3n71n0
  • 18
  • 3
  • See the error message in the question - `error: cannot bind non-const lvalue reference of type std::optional&` – Richard Critten May 11 '22 at 16:58
  • @RichardCritten How about this sentence in description: **However, when I try to change the optional return type to use a reference, i get errors like this**? – 73v3n71n0 May 11 '22 at 17:14