#include <memory>
#include <new>
#include <cstdlib>
#include <iostream>
template<typename T>
T*
allocate()
{
std::unique_ptr<T, void(*)(void*)> hold(static_cast<T*>(std::malloc(sizeof(T))),
std::free);
::new (hold.get()) T;
std::cout << hold.get() << std::endl;
return static_cast<T*>(hold.release());
}
template<typename B,typename T>
void
deallocate(B* p)
{
std::cout << p << std::endl;
T* d = static_cast<T*>(p);
d->~T();
std::cout << d << std::endl;
std::free(d);
}
struct Base
{
int i;
Base() {std::cout << "Base()\n";}
Base(const Base&) = delete;
Base& operator=(const Base&) = delete;
~Base() {std::cout << "~Base()\n";}
};
struct Derived
: public Base
{
int di;
Derived() {std::cout << "Derived()\n";}
Derived(const Base&) = delete;
Derived& operator=(const Derived&) = delete;
virtual ~Derived() {std::cout << "~Derived()\n";}
};
int
main()
{
std::unique_ptr<Derived, void(*)(Base*)> p(allocate<Derived>(), deallocate<Base,Derived>);
std::unique_ptr<Base, void(*)(Base*)> p2 = std::move(p);
std::unique_ptr<Derived, void(*)(Base*)> p3(allocate<Derived>(), deallocate<Base,Derived>);
}
I2luY2x1ZGUgPG1lbW9yeT4KI2luY2x1ZGUgPG5ldz4KI2luY2x1ZGUgPGNzdGRsaWI+CiNpbmNsdWRlIDxpb3N0cmVhbT4KCnRlbXBsYXRlPHR5cGVuYW1lIFQ+ClQqCmFsbG9jYXRlKCkKewogICAgc3RkOjp1bmlxdWVfcHRyPFQsIHZvaWQoKikodm9pZCopPiBob2xkKHN0YXRpY19jYXN0PFQqPihzdGQ6Om1hbGxvYyhzaXplb2YoVCkpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RkOjpmcmVlKTsKICAgIDo6bmV3IChob2xkLmdldCgpKSBUOwogICAgc3RkOjpjb3V0IDw8IGhvbGQuZ2V0KCkgPDwgc3RkOjplbmRsOwogICAgcmV0dXJuIHN0YXRpY19jYXN0PFQqPihob2xkLnJlbGVhc2UoKSk7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIEIsdHlwZW5hbWUgVD4Kdm9pZApkZWFsbG9jYXRlKEIqIHApCnsKCXN0ZDo6Y291dCA8PCBwIDw8IHN0ZDo6ZW5kbDsKICAgIFQqIGQgPSBzdGF0aWNfY2FzdDxUKj4ocCk7CiAgICBkLT5+VCgpOwogICAgc3RkOjpjb3V0IDw8IGQgPDwgc3RkOjplbmRsOwogICAgc3RkOjpmcmVlKGQpOwp9CgpzdHJ1Y3QgQmFzZQp7CglpbnQgaTsKICAgIEJhc2UoKSB7c3RkOjpjb3V0IDw8ICJCYXNlKClcbiI7fQogICAgQmFzZShjb25zdCBCYXNlJikgPSBkZWxldGU7CiAgICBCYXNlJiBvcGVyYXRvcj0oY29uc3QgQmFzZSYpID0gZGVsZXRlOwogICAgfkJhc2UoKSB7c3RkOjpjb3V0IDw8ICJ+QmFzZSgpXG4iO30KfTsKCnN0cnVjdCBEZXJpdmVkCiAgICA6IHB1YmxpYyBCYXNlCnsKCWludCBkaTsKICAgIERlcml2ZWQoKSB7c3RkOjpjb3V0IDw8ICJEZXJpdmVkKClcbiI7fQogICAgRGVyaXZlZChjb25zdCBCYXNlJikgPSBkZWxldGU7CiAgICBEZXJpdmVkJiBvcGVyYXRvcj0oY29uc3QgRGVyaXZlZCYpID0gZGVsZXRlOwogICAgdmlydHVhbCB+RGVyaXZlZCgpIHtzdGQ6OmNvdXQgPDwgIn5EZXJpdmVkKClcbiI7fQp9OwoKaW50Cm1haW4oKQp7CiAgICBzdGQ6OnVuaXF1ZV9wdHI8RGVyaXZlZCwgdm9pZCgqKShCYXNlKik+IHAoYWxsb2NhdGU8RGVyaXZlZD4oKSwgZGVhbGxvY2F0ZTxCYXNlLERlcml2ZWQ+KTsKICAgIHN0ZDo6dW5pcXVlX3B0cjxCYXNlLCB2b2lkKCopKEJhc2UqKT4gcDIgPSBzdGQ6Om1vdmUocCk7CiAgICBzdGQ6OnVuaXF1ZV9wdHI8RGVyaXZlZCwgdm9pZCgqKShCYXNlKik+IHAzKGFsbG9jYXRlPERlcml2ZWQ+KCksIGRlYWxsb2NhdGU8QmFzZSxEZXJpdmVkPik7CiAgICAKfQ==