Reputation: 5303
I have a ISceneNode interface and from that a SceneNode base class. From the SceneNode class derive MeshNode, AnimNode, LightNode, CameraNode, ect...
Now I have an actor class that through a method takes in a shared_ptr and stores it in a field.
What I'd like to be able to do is send in any std::shared_ptr or other derived classes into the function that takes in a shared_ptr .
With bare pointers this would be an implicit conversion.
The solution that I came up with was to write a overload for each of the derives and then cast it within the method using dynamic_pointer_cast . That's just nasty there should be a better way.
Is there a way to get implicit casting, or a better way I don't know of to handle this? What's the proper way to handle this?
void SomeFunc()
{
std::shared_ptr<MeshNode> pMeshNode( new MeshNode() );
gActor.SetNode( pMeshNode ); // won't compile.
// or do i have to do it like this
gActor.SetNode( std::dynamic_pointer_cast<ISceneNode> (pMeshNode) );
}
void Actor::SetNode( std::shared_ptr<ISceneNode> pNode )
{
mpNode = pNode;
}
// or do I have to do it like this? Making an over load for each derived.
void Actor::SetNode( std::shared_ptr<MeshNode> pMeshNode )
{
mpNode = std::dynamic_pointer_cast<ISceneNode> (pMeshNode);
}
Upvotes: 0
Views: 382
Reputation: 1393
I bet you are using VS2010? I found some problems with smart pointers support there? On a compiler with better C++11 support (eg. VS2012, gcc, clang) it should compile fine. However I would suggest you some extensions:
class Actor {
std::shared_ptr<ISceneNode> mpNode;
public:
void SetNode(std::shared_ptr<ISceneNode> pNode)
{ mpNode = std::move(pNode); }
};
void SomeFunc()
{
gActor.SetNode(std::make_shared<MeshNode>());
}
It is always better to allocate std::shared_ptr
with std::make_shared<T>()
which saves you one dynamic allocation and even up to the half of shared state memory overhead. You should also either pass std::shared_ptr
as a reference to a function or at least move it to a new value like I did. You could also consider using std::unique_ptr
which makes it even more effective (no shared state memory overhead and thread safe reference counting) and makes the design better (clear ownership). You can use in a very similar way:
class Actor {
std::unique_ptr<ISceneNode> mpNode;
public:
void SetNode(std::unique_ptr<ISceneNode> pNode)
{ mpNode = std::move(pNode); }
};
void SomeFunc()
{
gActor.SetNode(std::unique_ptr<MeshNode>(new MeshNode));
}
Upvotes: 2
Reputation: 11677
You claim it won't compile, but the following test compiles and runs for me (VS2012, Clang, G++). You should post the error you're getting, as it's most likely something else.
#include <memory>
struct IBase {};
struct Derived : IBase {};
void Foo(std::shared_ptr<IBase> p) {}
int main()
{
std::shared_ptr<Derived> d;
Foo(d);
}
Upvotes: 4