#include <iostream>
#include <list>
#include <memory>
using namespace std;

struct Connection
{
	Connection()
	{
		std::cout << "Connection()" << std::endl;
	}

	~Connection()
	{
		std::cout << "~Connection()" << std::endl;
	}
};

typedef shared_ptr<Connection> ptr_t;

class ConnectionReleaser {
    list<ptr_t>& whereToReturn;
    ptr_t connectionToRelease;
    int ver;
    static int nextVer;
public:
    ConnectionReleaser(list<ptr_t>& lst, const ptr_t& x)
    	: whereToReturn(lst)
    	, connectionToRelease(x)
    {
    	ver = nextVer++;
		std::cout << "ConnectionReleaser() v." << ver << std::endl;
    }

    ConnectionReleaser(const ConnectionReleaser& rhs)
    	: whereToReturn(rhs.whereToReturn)
    	, connectionToRelease(rhs.connectionToRelease)
    {
    	ver = nextVer++;
		std::cout << "ConnectionReleaser(rhs v." << rhs.ver << ") v." << ver << std::endl;
    }

	~ConnectionReleaser()
	{
		std::cout << "~ConnectionReleaser() v." << ver << std::endl;
	}

    void operator()(Connection*) {
        whereToReturn.push_back( connectionToRelease );
		// Обратите внимание на следующую строчку
        //connectionToRelease.reset();
    }
};

int ConnectionReleaser::nextVer = 0;


list<ptr_t> connectionList;

ptr_t getConnection() {
	std::cout << "enter getConnection()" << std::endl;
    ptr_t c( connectionList.back() );
    connectionList.pop_back();
    ptr_t r( c.get(), ConnectionReleaser( connectionList, c ) );
	std::cout << "exit getConnection()" << std::endl;
    return r; 
}

int main() {
	connectionList.push_back(make_shared<Connection>());
	
	{
	    weak_ptr<Connection> weak1;
		cout << "connectionList.size() = " << connectionList.size() << endl;
		auto c = getConnection();
		cout << "connectionList.size() = " << connectionList.size() << endl;
		weak1 = c;
		cout << "weak1.expired() = " << weak1.expired() << endl;
		cout << "begin c.reset()" << endl;
		c.reset();
		cout << "end c.reset()" << endl;
		cout << "weak1.expired() = " << weak1.expired() << endl;
		cout << "connectionList.size() = " << connectionList.size() << endl;
		cout << "deleting weak1" << endl;
	}
	
	return 0;
}