Reputation: 1760
I struggle with the complexity of conversions and casting, and I can't find advice online that clearly guarantees efficient conversion on function return. I have two classes, Base and Derived, where Derived has no extra data members over Base. I have a named constructor for the base class that I want to return using RVO and cast to an object of the derived type with as little overhead as possible.
class Base {
public:
static Base namedConstructor(int n){
return Base(n);
}
protected:
Base(int n) : member(n){
}
int member;
};
class Derived : public Base {
static Derived nC2(int n) {
Derived derived = namedConstructor(n);
// Error: no suitable user-defined conversion from "Base" to "Derived"...
// modify derived
return derived;
}
};
Is there a way to fix the error that satisfies all the following requirements?
Upvotes: 0
Views: 187
Reputation: 2554
I've added constructors and with g++ 3.0 there is copy elision:
class Base {
public:
static Base namedConstructor(int n){
return Base(n);
}
protected:
Base(int n) : member(n){
std::cout << "Create Base" << std::endl;
}
Base (const Base & b) : member (b.member) {
std::cout << "Copy Base" << std::endl;
}
int member;
};
class Derived : public Base {
public:
Derived () : Base (0) {
std::cout << "Create Derived" << std::endl;
}
Derived (const Base & b) : Base(b) {
std::cout << "Create Derived from base" << std::endl;
}
int val () { return member; }
static Derived nC2(int n) {
return namedConstructor(n); //derived;
}
};
int main ()
{
Derived d = Derived::nC2(1);
std::cout << "Value: " << d.val() << std::endl;
return 0;
}
The output from this is:
Create Base
Copy Base
Create Derived from base
Value: 1
so one Base
creation, one copy of Base
when creating Derived
and the Derived
itself.
There are no copies from namedConstructor
exit or nC2
, nor for the assignment in main
.
I've compiled this with -O0
but with those so small functions may be there is optimization here and those are removed.
Upvotes: 1
Reputation: 2836
Add a private
ctor. to Derived
, which constructs it from a Base
:
Derived(const Base& base) : Base(base) {
}
If later you add extra member variables to Derived
, initialize them also.
This is standard-compliant (although a little bit weird), and will be optimized away in release builds.
Upvotes: 1