I have a class with function called void deallocatorFunc(ClassA *p)
I want using templates make it possible to write boost::shared_ptr< ClassA > ptr(new ClassA());
instead of boost::shared_ptr< ClassA > ptr(new ClassA(), deallocatorFunc);
. I want it to spread on to my class and its inheritors. How to do such thing in C++? (I really need my peculiar destructor for that special class, while I want to keep super simple API).
Asked
Active
Viewed 367 times
1

myWallJSON
- 9,110
- 22
- 78
- 149
-
Could you overload `operator delete` for your type? – Lightness Races in Orbit Jan 26 '12 at 00:51
2 Answers
1
You can use specialization for your class and wrap the standard implementation. Here's a self-contained compilable example.
#include <iostream>
#include <boost/shared_ptr.hpp>
using namespace std;
class A
{
public:
A() {
cout << "Constructing A." << endl;
};
virtual ~A() {
cout << "Destructing A." << endl;
}
};
class B : public A
{
public:
B() {
cout << "Constructing B." << endl;
};
virtual ~B() {
cout << "Destructing B." << endl;
}
};
class C
{
public:
C() {
cout << "Constructing C." << endl;
};
virtual ~C() {
cout << "Destructing C." << endl;
}
};
void deallocatorFunc(A *p)
{
cout << "Deallocator function." << endl;
delete p;
};
namespace boost {
template<> class shared_ptr<A> {
private:
shared_ptr<void> _ptr;
public:
shared_ptr(A* p) : _ptr(p, deallocatorFunc)
{
}
};
}
int main( int argc, const char* argv[] )
{
boost::shared_ptr<A> ptrA(new A());
boost::shared_ptr<B> ptrB(new B());
boost::shared_ptr<C> ptrC(new C());
}
Output:
Constructing A. Constructing A. Constructing B. Constructing C. Destructing C. Destructing B. Destructing A. Deallocator function. Destructing A.
Note
As given, the specialization doesn't work for derived classes of A!
For that to work, you need more trickery:
-
You're demonstrating explicit specialization, not partial specialization. – ildjarn Jan 26 '12 at 01:29
0
namespace boost {
template<typename myclass> class shared_ptr {
};
}
Enjoy your redefinition of boost::shared_ptr. Anything which includes the above code in a header will get your shared_ptr
instead of boost's.
Keep in mind this will not be compatible with code which includes boost on its own!!!

Borealid
- 95,191
- 9
- 106
- 122
-
Is it any how possible tojust overload/specialize boost shared_ptr creation for one class type keeping it compatible with code which includes boost on its own? – myWallJSON Jan 26 '12 at 00:58
-
@myWallJSON : No, but you could make your constructor private and force people to use factory functions to allocate objects on the freestore (the factory functions would use the correct semantics). – ildjarn Jan 26 '12 at 01:10
-
@ildjarn: of course it's possible, he just needs to override one template specialization of `shared_ptr` and copy through the remainder. – Borealid Jan 26 '12 at 01:16
-
If you think that's true then you should elaborate more. I don't think it's true, but I don't know what you mean by "*override one template specialization of `shared_ptr` and copy through the remainder*" because that doesn't make much sense to me. (And how would whatever that is avoid violating the ODR?) – ildjarn Jan 26 '12 at 01:17
-
@ildjarn: The ODR applies to template instantiations, not template declarations. You may have a template where "if the parameter is `MyClass`, use this version, otherwise use the generic catch-all". See http://www.gotw.ca/gotw/049.htm as a random off-the-web resource. – Borealid Jan 26 '12 at 01:21
-
1) An explicit specialization, as you seem to be advocating (I'm still not clear), is not a template at all. 2) _Instantiations_ of `boost::shared_ptr
` in external code lacking said specialization will have different definitions than local code with the specialization -- this does violate the ODR. – ildjarn Jan 26 '12 at 01:23 -
@ildjarn: as I said, this is incompatible with code using the "real" `boost::shared_ptr`. – Borealid Jan 26 '12 at 01:50
-
You also said "*of course it's possible*", so you're contradicting yourself yet again. – ildjarn Jan 26 '12 at 01:51
-
@ildjarn: I didn't mean the user code includes the boost headers. If they include your header *instead*, and of the remainder of the code could work (you can pass through the legitimate boost functionality). – Borealid Jan 26 '12 at 02:06