Skip to content

Instantly share code, notes, and snippets.

@eao197
Created July 21, 2020 05:36
Show Gist options
  • Select an option

  • Save eao197/b1f4d19703997954abdcd04dc554f48c to your computer and use it in GitHub Desktop.

Select an option

Save eao197/b1f4d19703997954abdcd04dc554f48c to your computer and use it in GitHub Desktop.
Развитие идеи protected_ptr, предложенной Николаем Меркиным в обсуждении в FB.
#include <memory>
#include <iostream>
#include <string>
using namespace std;
template< typename T >
class protected_ptr
{
shared_ptr<T> m_object;
public:
protected_ptr() = default;
template< typename U >
protected_ptr( U * o ) : m_object{ o } {}
template< typename U >
protected_ptr( shared_ptr<U> o ) : m_object{ std::move(o) } {}
template< typename U >
protected_ptr( protected_ptr<U> o ) : m_object{ o.m_object } {}
shared_ptr<T>
operator->() const noexcept { return m_object; }
};
template< typename T >
class enable_protected_from_this
: public enable_shared_from_this<T>
{
private:
using enable_shared_from_this<T>::shared_from_this;
public:
protected_ptr<T>
protected_from_this() { return { shared_from_this() }; }
protected_ptr<const T>
protected_from_this() const { return { shared_from_this() }; }
};
class Parent;
class Child : public enable_protected_from_this<Child>
{
protected:
Parent * m_parent;
public:
Child( Parent * parent ) : m_parent{ parent } {}
virtual ~Child() = default;
virtual void on_start() = 0;
};
using child_ptr = protected_ptr<Child>;
class Parent
{
child_ptr m_current_child;
public:
void remove_child() { m_current_child = {}; }
void replace_child( child_ptr new_child )
{
m_current_child = std::move(new_child);
m_current_child->on_start();
}
};
class ActualChild : public Child
{
std::string m_name;
bool m_first;
ActualChild( Parent * parent, std::string name, bool first )
: Child{ parent }
, m_name{ std::move(name) }
, m_first{ first }
{
std::cout << m_name << ": created (" << m_first << ")" << std::endl;
}
void activate()
{
m_parent->replace_child( protected_from_this() );
}
public:
ActualChild( Parent * parent, std::string name )
: Child{ parent }
, m_name{ std::move(name) }
, m_first{ true }
{
std::cout << m_name << ": created" << std::endl;
}
~ActualChild() override
{
std::cout << m_name << ": destroyed" << std::endl;
}
void on_start() override
{
std::cout << m_name << ": started" << std::endl;
if( m_first )
{
auto another_child = shared_ptr<ActualChild>(
new ActualChild{ m_parent, m_name + ".next", false } );
another_child->activate();
}
else
m_parent->remove_child();
std::cout << m_name << ": finished" << std::endl;
}
};
int main()
{
Parent parent;
parent.replace_child( new ActualChild{ &parent, "demo" } );
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment