[xsd-users] C++11, value semantics, and polymorphism

Boris Kolpackov boris at codesynthesis.com
Mon Feb 25 06:46:55 EST 2013


Hi Ray,

Ray Lischner <rlischner at proteuseng.com> writes:

> Our use of Code Synthesis often involves the construction of objects
> from other objects, so we end up with code sort like this:
> 
> A a(B("string", C(D("string", value), "string", "string")));
> 
> except that some of those types are polymorphic. Right now, we can create
> all the intermediate objects dynamically and sling auto_ptr<>s around to
> avoid excess copying. With C++ 11, we want to use value semantics where
> possible, but that forces the user to know which types are polymorphic and
> which are not, so we end up with the following:
> 
> A a(B("string", new C(D("string", value), "string", "string")));

Hm, I think we can handle this without resorting to the pimpl stuff. Let's
take a simple case:

A a (D ("string"));

Where the argument is of a polymorphic type B:

A (const B&);

Right now, to avoid copying you are doing essentially this:

A a (new D ("string"));

What if we overload the A() ctor and do "polymorphic move", similar to
the "polymorphic copy" (aka clone), that we are already doing. In other
words:

A (const B& b)
{
  b_ = b->_clone (); // _clone() uses copy ctor.
}

A (B&& b)
{
  b_ = b->_move (); // _move() uses move ctor.
}

Now, when you write:

A a (D ("string"));

Compared to the dynamic allocation, you are only paying the penalty of
constructing D on the stack (which will then be moved into the dynamically
allocated instance inside _move()). Presumably this will be cheap.

Here is how _move() is implemented:

D* D::
_move () // Note: non-const, unlike _clone ().
{
  return new D (std::move (*this)); // Using move ctor.
}

There is just one problem: the combinatorial explosion of constructors
resulting from const-ref/rvalue-ref overloads. You can read more about
the issue in this series of blog posts:

http://www.codesynthesis.com/~boris/blog/2012/06/19/efficient-argument-passing-cxx11-part1/

Unfortunately, the solution that I propose (pass by value) won't work
here (we will end up slicing polymorphic objects). Need to thinks more
on this. Any ideas are welcome.

Boris



More information about the xsd-users mailing list