#include <iostream>
#include <utility>
#include <cstddef>

template <typename T>
struct my_shared_ptr
{
	my_shared_ptr() : rc(0) {}

	template <typename... Args>
	my_shared_ptr(Args&&... args)
		: rc(new refcount_block(std::forward<Args>(args)...))
	{}

	T& operator * ()
	{
		return *rc->ptr();
	}

	T* operator -> ()
	{
		return rc->ptr();
	}

	~my_shared_ptr()
	{
		if(!--rc->refs)
			delete rc;
	}

private:
	struct refcount_block
	{
		template <typename... Args>
		refcount_block(Args&&... args)
			: refs(1)
		{
			new (object) T(std::forward<Args>(args)...);
		}

		~refcount_block()
		{
			ptr()->~T();
		}

		T* ptr()
		{
			return reinterpret_cast<T*>(object);
		}

		std::size_t refs;
		char object[sizeof(T)]; // alignas(T)
	};

	refcount_block* rc;
};

int main()
{
	std::cout << sizeof(int*)                 << '\n'
	          << sizeof(my_shared_ptr<int>)   << '\n';
}