読者です 読者をやめる 読者になる 読者になる

unique_ptr<void>でデストラクタを呼ぶ

C++

std::shared_ptr<void>は、代入された任意の型のデストラクタが適切に呼び出されるが、std::unique_ptr<void>はできない。この提案は、それをなんとかしようというもの。

技術的には、こういうことをする:

#include <iostream>
#include <memory>

struct X {
    ~X()
    {
        std::cout << "destructor" << std::endl;
    }
};

struct void_deleter {
    std::function<void(void*)> deleter;

    template <class F>
    void_deleter(F f)
    {
        deleter = f;
    }

    void operator()(void* p) const noexcept
    {
        deleter(p);
    }
};

int main()
{
    std::unique_ptr<void, void_deleter> p(
        new X(),
        [](void* p) { delete static_cast<X*>(p); }
        );
}

出力:

destructor

つまり、任意の型のポインタが代入された時点で、「void*型のポインタから任意の型のポインタにキャストしてdeleteする」関数オブジェクトを持たせる。これも一種のType Erasure。

ここではstd::functionでそのような関数オブジェクトを保持しているが、実際の提案では、キャプチャなしのラムダ式を関数ポインタに変換して持っているため、ほぼコストがない。

このような実装を、std::unique_ptrvoidに対する特殊化として用意し、std::unique_ptrコンストラクタ/代入演算子内部でこういうことをする、というのがこの提案。