There's a problem I have with proxy objects and move semantics. They don't always combine very well. In my container class I have and overloaded operator[]
that employs lazy element creation within the container. So operator[]
returns a proxy object that keeps either a reference to an existing element of container or a place for the potential new element. The idea is that whenever proxy object is accessed in a specific manner or when something is assigned to it, a new element is automatically created in the container in that place.
The problem is in the way the proxy object is returned:
Proxy operator [](std::string name);
I am forced to return by value because I want the caller to manage the lifetime of proxy. The problem with returning by value is that the result of operator []
call is a prvalue, meaning that it will always be moved whenever function is called to initialize or assign a new object:
/// Element of container identified by name "foo" is moved from.
Element foo(container["foo"]);
/// Same with bar...
foo = container["bar"];
I want my proxy to be move assignable to an element, to have a smoth user-expirience. But I want it to be in a usual, expected fasion, like this:
Element foo = std::move(container["foo"]);
For all I know, it can be achieved through a second proxy object MovableProxy
. According to this strategy, I want to configure Proxy
in such a way that it can only be copied. Then I want to specialize std::move
for Proxy
type so it will return MovableProxy
when supplied with a rvalue or lvalue of Proxy
:
namespace std
{
MovableProxy move(Proxy & foo)
{
...
}
MovableProxy move(Proxy && foo)
{
...
}
} // namespace std
So, how bad is an idea of specializing template function std::move
for my own class? And what awful pitfalls are waiting around the corner.
Aucun commentaire:
Enregistrer un commentaire