You can't copy and move only once, unless you change the design of your classes and turn their constructors into (possibly SFINAE-constrained) templated forwarding constructors (Yakk's answer shows how).
While doing that would make it possible to perform just one move and no copy when rvalues are provided, and one copy and no moves when lvalues are provided, it is an overkill in most situations.
As an alternative to the template-based forwarding constructors, you could provide two constructors, both in your base class and in your derived class: one for rvalue references and one for lvalue references to const
. But again, that's an unnecessary complication in most scenarios (and doesn't scale well when the number of arguments increases, since the number of required constructors would increase exponentially).
Moving an std::string
is as fast as copying a pointer and an integer (ignoring SSO optimization here), and you should not bother about it unless you have real evidence that this is a bottleneck that prevents your application from meeting its performance requirements (hard to believe).
Therefore, just let your Derived
constructor take its argument by value unconditionally, and move it when passing it to the base class's constructor:
class Derived : public Base
{
public:
Derived(std::string text) : Base(std::move(text)) { }
};
Another option, in case you want (or accept) Derive
to inherit all of Base
's constructors, is to exploit C++11's inherited constructors like so:
class Derived : public Base
{
public:
using Base::Base;
// ^^^^^^^^^^^^^^^^^
};