How does shared_ptr <T> detect that T comes from enable_shared_from_this <T>?
I'm trying to figure out how shared_ptr works by implementing it from scratch and I can't figure out how to define the base class T.
I've tried using is_base_of (), but that gives a const value that I can't use with an if statement to set an internal weak_ptr object.
I thought about it:
template <class T>
class shared_ptr
{
shared_ptr(T* ptr)
{
...
}
shared_ptr(enable_shared_from_this<T>* ptr)
{
...
Ptr->m_this = weak_ptr<T>(this);
}
};
but no luck yet. The Boost and VC ++ installations are too confusing for me, I am looking for a simple explanation.
The std :: shared_ptr constructors detect the presence of the enable_shared_from_this base and assign the newly created std :: shared_ptr to the internally saved weak reference.
But how?
source to share
Simple template argument usage! This is the solution to all the world's problems, but you already knew it :) The boost-based solution solves your problem below. We create a templated helper class that actually handles the design details.
template <class T>
class shared_ptr
{
shared_ptr(T* ptr)
{
magic_construct(this, ptr, ptr);
}
};
template <class X, class Y, class Z>
void magic_construct(shared_ptr<X>* sp, Y* rp, enable_shared_from_this<Z>* shareable)
{
//Do the weak_ptr handling here
}
void magic_construct(...)//This is the default case
{
//This is the case where you have no inheritance from enable_shared_from_this
}
source to share
One option is to make it based on function template overloading.
Here's a simplified solution: We have two classes A and B. Class A derives from H. The function is is_derived_from_h
overloaded and can be used to determine if any class X derives from H.
#include <stdlib.h>
#include <iostream>
class H {};
class A: public H {};
class B {};
// (1)
template <typename X>
void is_derived_from_h(X* px, H* ph) {
std::cout << "TRUE" << std::endl;
}
// (2)
void is_derived_from_h(...) {
std::cout << "FALSE" << std::endl;
}
int main(int argc, char* argv[]) {
A* pa = new A;
B* pb = new B;
is_derived_from_h(pa, pa); // (1) is selected, the closest overload
is_derived_from_h(pb, pb); // (2) is selected, (1) is not viable
delete pa;
delete pb;
return EXIT_SUCCESS;
}
Output:
TRUE
FALSE
In the case of Boost, trace the following calls:
shared_ptr( Y * p )
->
boost::detail::sp_pointer_construct( this, p, pn );
->
boost::detail::sp_enable_shared_from_this( ppx, p, p );
Here are several versions sp_enable_shared_from_this
. The version chosen depending on whether Y is received from enable_shared_from_this
or not.
source to share