#include <iostream>
#include <memory>
#include <string>

class Person
{
	std::string m_name;
    std::shared_ptr<Person> m_partner;
    //std::weak_ptr<Person> m_partner;
    
public:
    Person(const std::string &name) : m_name(name)
    {
        std::cout << m_name << " created\n";
    }
    ~Person()
    {
        std::cout << m_name << " destroyed\n";
    }
    
    friend bool partnerUp(std::shared_ptr<Person> &p1, std::shared_ptr<Person> &p2)
    {
        if (!p1 || !p2)
            return false;
        
        p1->m_partner = p2;
        p2->m_partner = p1;
        
        std::cout << p1->m_name << " is partnered with" << p2->m_name << "\n";
        
        return true;
    }
    
    const std::shared_ptr<Person> getPartner() const
    {
        return m_partner.lock();
    }
    
    const std::string & getName() const
    {
        return m_name;
    }
};

int main()
{
    auto lucy = std::make_shared<Person>("Lucy");
    auto ricky = std::make_shared<Person>("Ricky");
 
    partnerUp(lucy, ricky); // -> Lucy, Ricky가 destroyed가 안됨. Person class에서 m_partner가 순환되기 때문이다. weak_ptr을 쓰면 됨
    						// 순환 의존성 문제 해결
    						// weak_ptr을 쓸 땐 .lock()을 해주어야 한다. return 값이 shared_ptr로 return 해준 후에 사용
    
    std::cout << lucy->getPartner()->getName() << "\n";
    
    return 0;
}