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:
- Is it a normal design to implement
WidgetProxy::setName()like this? - Should a library user normally expect such behavior when they see a
const shared_ptr<T>&function parameter?
Aucun commentaire:
Enregistrer un commentaire