   Smart pointers and COM development
  Having decided to start using smart pointers from the boost library I have come across several theoretical questions that relate to programming style and which might even belong to beginner's forum:How often should I use the smart pointers?How should I go around those crazy long names like std::vector<boost::shared_ptr<Object>>? Is using a localized typedef a common method?And mainly, what should I do when mixing normal pointers with COM pointers? COM interface uses ->Release() instead of delete and deleting objects manually can lead to memory corruption so the smart_ptr is unusable. There is COMPtr advailable but I'm not sure if it's good to mix two types of pointers in 1 application. What should I do about those ->Release() functions? Thank you in advance.   
Quote:Original post by RatslayerHow should I go around those crazy long names like std::vector<boost::shared_ptr<Object>>? Is using a localized typedef a common method?yes, it's the common method.  It won't prevent you from getting crazy compiler errors, but it does tons for readability and making code smaller.Quote:And mainly, what should I do when mixing normal pointers with COM pointers? COM interface uses ->Release() instead of delete and deleting objects manually can lead to memory corruption so the smart_ptr is unusable. There is COMPtr advailable but I'm not sure if it's good to mix two types of pointers in 1 application. What should I do about those ->Release() functions? Thank you in advance.It's fine to mix CComPtr and other types of smart pointers.  just don't do anything like making boost::shared_ptr<CComPtr> because it's unnecessary.Personally I'm against CComPtr because I think it's silly to introduce a dependency on a clunky, massive library for exactly 1 class, and also since CComPtr overloads the & operator, which is a disaster waiting to happen.  So I use boost::intrusive_ptr<> for com pointers.  You have to write some of your own code to support it, but it's basically just you providing an intrusive_ptr_add_ref(IUnknown*) and intrusive_ptr_delete(IUnknown*) function, and delegating to p->AddRef() and p->Release().   ;Quote:Original post by RatslayerHow should I go around those crazy long names like std::vector<boost::shared_ptr<Object>>? Is using a localized typedef a common method?I like to add a shared_ptr typedef class as a member type.class Object{  public:  typedef boost::shared_ptr<Object> ptr;};//use as...Object::ptr my_ptr(new Object);;Quote:Original post by cache_hit...and also since CComPtr overloads the & operator, which is a disaster waiting to happen.In most cases I would agree about that sort of operator overloading, but in this particular case I think the convenience outweighs the evil-ness. Or at least, if you're working with a library like DX where just about every object is created through through a function where you need to pass a pointer to an interface pointer.   ;Quote:Original post by cache_hitCComPtr overloads the & operator, which is a disaster waiting to happen.I've never had problems with that. CAdapt is there to help in the rare cases where it could/would pose a problem. Personally I wouldn't really want to use COM without ATL, but I guess it's different in game development where you're more likely to use COM classes, than to write your own.Also, if you think that's bad then there's also _com_ptr_t whose address-of operator overload releases whatever it currently holds. That can be particularly nasty, especially if you're not aware of it.   ;Quote:Original post by MJPQuote:Original post by cache_hit...and also since CComPtr overloads the & operator, which is a disaster waiting to happen.In most cases I would agree about that sort of operator overloading, but in this particular case I think the convenience outweighs the evil-ness. Or at least, if you're working with a library like DX where just about every object is created through through a function where you need to pass a pointer to an interface pointer.There are ways around that.  whenever you would normally have to pass an IUnknown** that would receive an interface pointer, you can make your own class called recv_com_ptr which takes an IUnknown*& in the constructor, and has an overloaded operator IUnknown**.  I wrote one of these before but don't have the source handy at the moment.I agree it's annoying, but think of the alternative.  what happens if you make a vector<CComPtr>?  What happens if you put CComPtr in *any* STL or boost container for that matter?  Who knows really, maybe it works, but most likely there's a case where it doesn't.  Quote:I've never had problems with that. CAdapt is there to help in the rare cases where it could/would pose a problem. Personally I wouldn't really want to use COM without ATL, but I guess it's different in game development where you're more likely to use COM classes, than to write your own.The problem is having to know when it would pose a problem.  More things to think about = more potential for bugs.  If you do it in a type safe manner (i.e. by making *correct* versions of the useful ATL classes), you don't have to worry about anything and it's never a problem.   ;  You might also look at using boost::instrusive_ptr.  It can allow you to make a smart pointer that uses COM's AddRef and Release functions, with basically the same interface as shared_ptr.   ;  So how would I change the boost::intrusive_ptr to handle COM pointers? I guess I can make a child class with an overloaded destructor that converts the pointer to IUnknown* and then, after checking with IUnknown->Valid(), uses IUnknown->Release(). But what do I do with AddRef? There is no helper fuction one can overload in this case, how should I go around integrating COM AddRef in boost::intrusive_ptr?   ;  Intrusive pointer is basically a smart pointer that will use a class's own reference counting system (e.g. COM).  You just have to show it how to call the class's existing interface.Here is a snippet of code I used when I was implementing COM drag and drop.  The COM object was IDataObject.typedefboost::intrusive_ptr<IDataObject>IDataObjectPointer;namespace boost{inline void intrusive_ptr_add_ref(IDataObject* p){const ULONG _Count(p->AddRef());}inline void intrusive_ptr_release(IDataObject* p){const ULONG _Count(p->Release());}}[edit]The storing of the count is basically just for debugging purposes.  You can reduce them to just the calls to AddRef and Release.   ;  If you change IDataObject* to IUnknown* then you can automatically make intrusive_ptr<T> for any type T that derives from IUnknown, since it only has to do an upcast it will always delegate to the correct function.   