jeudi 10 août 2017

Is modifying data passed by const shared_ptr& Ok?

I've come across a situation where I needed to set a property to a library object by means of a setter accepting const shared_ptr reference. Here is a simple example:

// library class
class WidgetProxy {
public:
    void setName(const std::shared_ptr<std::string>& name);
    // more methods
};

Suspecting nothing, I used it like this:

WidgetProxy widgetProxy(...);

auto name = std::make_shared<std::string>("Turing");
widgetProxy.setName(name);

// continue using `name`

Then I've found out that name had become empty after setName() call. Luckily, library source code was available and I was able to examine the implementation. It was roughly the following:

class WidgetImpl {
public:
    void setName(std::string name)
    {
        name_ = std::move(name);
    }

private:
    std::string name_;
};

void WidgetProxy::setName(const std::shared_ptr<std::string>& name)
{
    widgetImpl_.setName(std::move(*name));
}

So setName() moves out the string wrapped by the shared_ptr which is formally not prohibited since shared_ptr template argument is std::string and not const std::string.

My questions:

  1. Is it a normal design to implement WidgetProxy::setName() like this?
  2. Should a library user normally expect such behavior when they see a const shared_ptr<T>& function parameter?

Aucun commentaire:

Enregistrer un commentaire