#include <iostream>
#include <memory>
#include <vector>

struct A {
	std::string s = "foo";
	std::weak_ptr<A> h;
	std::shared_ptr<A> && getR() {
		return std::move(h.lock());
	}
	std::shared_ptr<A> getL() {
		return h.lock();
	}
};

std::vector< std::shared_ptr<A> > storage;
std::vector< std::weak_ptr<A> > accountant;

void store(std::shared_ptr<A> && rr) {
	std::cout << "store '" << rr->s << "' uses: " << rr.use_count() << std::endl;
	storage.push_back(std::move(rr));
}

int main() {
	// create keeper of A
	auto keeper = std::make_shared<A>();
	keeper->s = "bar";
	// store weak_ptr-type handle with accountant
	accountant.push_back(keeper);
	// backref handle to A
	keeper->h = accountant[0];
	
	std::cout << "# case 0: manual 'move'" << std::endl;
	{
		store(std::move(accountant[0].lock()));
		
		std::cout << "uses: " << keeper.use_count() << std::endl;
	}
	storage.clear();

	std::cout << "# case 1: manual 'move' from internal" << std::endl;
	{
		store(std::move(keeper->h.lock()));
		
		std::cout << "uses: " << keeper.use_count() << std::endl;
	}
	storage.clear();
	
	std::cout << "# case 2: return copy from func" << std::endl;
	{
		store(keeper->getL());
		
		std::cout << "uses: " << keeper.use_count() << std::endl;
	}
	storage.clear();
	// all is well up to here.
	
	std::cout << "# case 3: return rref from func" << std::endl;
	{
		store(keeper->getR());
		
		std::cout << "uses: " << keeper.use_count() << std::endl;
		std::cout << "storage[0]: " << storage[0].get() << " uses: " << storage[0].use_count() << " " << &storage[0] << std::endl;
		std::cout << "keeper: " << keeper.get() << " uses: " << keeper.use_count() << " " << &keeper << std::endl;
	}
	storage.clear();

	std::cout << "# after" << std::endl;
	std::cout << "uses: " << keeper.use_count() << std::endl;
	// all the A is gone!!!!
	return 0;
}