Question
How to return smart pointers and covariance in C++
I am following this tutorial to understand how to return smart pointers and covariance in C++.
#include <memory>
#include <iostream>
class cloneable
{
public:
virtual ~cloneable() {}
std::unique_ptr<cloneable> clone() const
{
return std::unique_ptr<cloneable>(this->clone_impl());
}
private:
virtual cloneable * clone_impl() const = 0;
};
///////////////////////////////////////////////////////////////////////////////
template <typename Derived, typename Base>
class clone_inherit: public Base
{
public:
std::unique_ptr<Derived> clone() const
{
return std::unique_ptr<Derived>(static_cast<Derived *>(this->clone_impl()));
}
private:
virtual clone_inherit * clone_impl() const override
{
return new Derived(*this); // getting error here
}
};
class concrete : public clone_inherit<concrete, cloneable>
{
};
int main()
{
std::unique_ptr<concrete> c = std::make_unique<concrete>();
}
When I execute this example I get the following error:
/tmp/0RmVdQYjfA.cpp: In instantiation of 'clone_inherit<Derived, Base>* clone_inherit<Derived, Base>::clone_impl() const [with Derived = concrete; Base = cloneable]':
/tmp/0RmVdQYjfA.cpp:30:28: required from here
/tmp/0RmVdQYjfA.cpp:32:14: error: no matching function for call to 'concrete::concrete(const clone_inherit<concrete, cloneable>&)'
32 | return new Derived(*this);
| ^~~~~~~~~~~~~~~~~~
/tmp/0RmVdQYjfA.cpp:37:7: note: candidate: 'constexpr concrete::concrete()'
37 | class concrete : public clone_inherit<concrete, cloneable>
| ^~~~~~~~
/tmp/0RmVdQYjfA.cpp:37:7: note: candidate expects 0 arguments, 1 provided
/tmp/0RmVdQYjfA.cpp:37:7: note: candidate: 'constexpr concrete::concrete(const concrete&)'
/tmp/0RmVdQYjfA.cpp:37:7: note: no known conversion for argument 1 from 'const clone_inherit<concrete, cloneable>' to 'const concrete&'
/tmp/0RmVdQYjfA.cpp:37:7: note: candidate: 'constexpr concrete::concrete(concrete&&)'
/tmp/0RmVdQYjfA.cpp:37:7: note: no known conversion for argument 1 from 'const clone_inherit<concrete, cloneable>' to 'concrete&&'
To fix this error in line 32, I had to return exactly the return pointer to a Derived class as follows:
// return new static_cast<Derived*>(*this); to replace with
return new Derived(static_cast<const Derived&>(*this));
Can someone suggest the proper way to fix this?
2 92
2