Sign in to follow this  
KaiserJohan

Casting boost weak_ptr<T> to my class

Recommended Posts

KaiserJohan    2317
Hello,

I have a GameObjectFactory which creates/destroys a GameObject with the following methods:
mMemoryMgr is a custom memory allocation/deallocation module


[code]

template <class T>
inline static void DestroyObject(T* obj)
{

mMemoryMgr->Deallocate(obj);
}

// T is supposed to be a derived class of GameObject

template <class T>
inline boost::shared_ptr<T> CreateObject()
{
boost::shared_ptr<T> sPtr((T*) mMemoryMgr->Allocate(sizeof(T)),DestroyObject<T> );

// get a weak_ptr from shared_ptr and cast its object to gameobject
boost::weak_ptr<GameObject> wPtr = boost::static_pointer_cast<boost::shared_ptr<GameObject>>(sPtr);

// add it to some container of weak_ptr<gameobject>
mObject.push_back(wPtr);


return sPtr;
}
[/code]

I have the following problems though with my design;

1. I get the following errors when trying to cast the shared_ptr<T> to weak_ptr<GameObject>:

Error 2 error C2440: 'initializing' : cannot convert from 'boost::shared_ptr<T>' to 'boost::weak_ptr<T>'
Why is this?

2. I'm new to template programming; Is there any way to 'enforce' in compile time in CreateObject() that T is derived from GameObject through a predicate or something?
such as template <class T where T is derived from GameObject>...

Thanks

Share this post


Link to post
Share on other sites
SiCrane    11839
1) boost::shared_pointer_cast<>'s template argument should be the type parameter of the shared pointer type, not the shared pointer's type. In other words [tt]boost::static_pointer_cast<gameobject>(sPtr);[/tt] instead of [tt]boost::static_pointer_cast<boost::shared_ptr<GameObject>>(sPtr)[/tt]. However, in this case, the cast isn't necessary. You can construct a weak_ptr to a base class directly from a shared_ptr to a derived class.

2) You can't apply constraints of that sort with C++'s templates. In this case, if you try using the template with a class that doesn't have an implicit conversion from it's pointer type to GameObject * then you'll get a compiler error.

Also, as mentioned in your previous thread, you're still passing an unconstructed object to the shared_ptr. Further, your clean up function doesn't call the destructor when all the shared_ptrs go out of scope.

Share this post


Link to post
Share on other sites
wqking    761
1, I'm not familiar with Boost smart pointers. But I think you need to construct a new weak pointer from T?
2, There is type traits library in Boost, and there is is_base_of. You can use it to check if GameObject is base of T. If you want compile time enforce, there is enable_if in Boost. See using enable_if here,
http://www.boost.org/doc/libs/1_49_0/libs/utility/enable_if.html

Share this post


Link to post
Share on other sites
KaiserJohan    2317
[quote name='SiCrane' timestamp='1333288654' post='4927175']
1) boost::shared_pointer_cast<>'s template argument should be the type parameter of the shared pointer type, not the shared pointer's type. In other words [tt]boost::static_pointer_cast<gameobject>(sPtr);[/tt] instead of [tt]boost::static_pointer_cast<boost::shared_ptr<GameObject>>(sPtr)[/tt]. However, in this case, the cast isn't necessary. You can construct a weak_ptr to a base class directly from a shared_ptr to a derived class.

2) You can't apply constraints of that sort with C++'s templates. In this case, if you try using the template with a class that doesn't have an implicit conversion from it's pointer type to GameObject * then you'll get a compiler error.

Also, as mentioned in your previous thread, you're still passing an unconstructed object to the shared_ptr. Further, your clean up function doesn't call the destructor when all the shared_ptrs go out of scope.
[/quote]

Thanks, I missed that. It works nicely.
There is one thing that boogles me though; how do I supply constructor arguments to my GameObject baseclass? When I call placement new with T(), it then also calls GameObjects constructor too right, but if I pass arguments to T() then the derived class gets those arguments passed to it, rather than my baseclass?

Edit: For example, I want to pass the GameObject its ID and I don't want to expose a public method to do it

Share this post


Link to post
Share on other sites
SiCrane    11839
A derived class can call a base class constructor via the member initialization list. Ex:
[code]
struct Base {
Base(int id) {
// stuff
}
};

struct Derived : Base {
Derived(int id) : Base(id) {
// stuff
}
};
[/code]

Share this post


Link to post
Share on other sites
KaiserJohan    2317
[quote name='SiCrane' timestamp='1333291776' post='4927185']
A derived class can call a base class constructor via the member initialization list. Ex:
[code]
struct Base {
Base(int id) {
// stuff
}
};

struct Derived : Base {
Derived(int id) : Base(id) {
// stuff
}
};
[/code]
[/quote]

Aye, but that means each derived class has to manually construct it like that. Is there any way to automate and hide this process from the derived classes?

Edit: how the 'friend' classes work? I've heard the concept but havn't found any good example use of it - maybe thats a good idea?

Share this post


Link to post
Share on other sites
SiCrane    11839
If you want to pass an argument to a base class constructor, then a derived class constructor has to do it. That's just how C++ works. Friending another class just gives that other class access to private and protected members of the first class. It doesn't affect construction in any way.

Share this post


Link to post
Share on other sites
KaiserJohan    2317
[quote name='SiCrane' timestamp='1333296653' post='4927196']
If you want to pass an argument to a base class constructor, then a derived class constructor has to do it. That's just how C++ works. Friending another class just gives that other class access to private and protected members of the first class. It doesn't affect construction in any way.
[/quote]

I thought GameObjectFactory could friend the GameObject so it could set the ID etc without having the GameObject revealing a public method for it

Share this post


Link to post
Share on other sites
SiCrane    11839
Other way around. GameObject could friend GameObjectFactory if it wants to allow GameObjectFactory to access non-public members of GameObject.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this