web-dev-qa-db-ja.com

std :: make_uniqueをカスタムの削除機能とともに使用する

カスタム削除機能でstd::unique_ptrを使用する場合、未加工の新しいものではなくstd::make_uniqueを使用したいと思います。 VC++ 2013を使用しています。カスタムの削除機能を使用している場合、std::unique_ptrを使用する方法はないと思われます。私は何かを逃したのですか、それとも本当ですか?


追加情報:

開いているCOMポートのWindowsハンドルを保持するためにstd::unique_ptr<HANDLE, custom_deleter>を使用しています。

このためのカスタムRAIIクラスを作成することはできましたが、それほど難しくはありませんでしたが、std::unique_ptrを使用することの難しさ、難しさ、悪さを実感していました。

32
Graznarak

make_uniqueの要点は、「newを使用してT与えられたコンストラクタ引数からを作成し、deleteを使用して破棄する」という概念をカプセル化することです。

カスタムの削除機能が必要な場合は、createオブジェクトをどのように指定するかを指定する必要があります。その場合、emplacing maker関数を使用することで得られるものはありません。

特定の一意のリソースハンドルのカスタムメーカー関数の例をいくつか書きました この投稿では

25
Kerrek SB

カスタムのフリー関数を呼び出すカスタムの削除機能を使用して、Cスタイルのメモリ管理をstd::unique_ptrにラップする方法を次に示します。これには、std::make_unique[〜#〜] live [〜#〜] に類似したmake関数ヘルパーがあります。

#include <iostream>
#include <functional>
#include <memory>

// Some C style code that has some custom free function ptr...
extern "C" {

struct ABC { };

enum free_type_e {
    FREE_ALL,
    FREE_SOME
};

typedef void (free_f)(enum free_type_e free_type, void *ptr);
struct some_c_ops { free_f* free_op; };

void MY_free(enum free_type_e free_type, void *ptr)
{
    printf("%s:%d ptr=%ld\n", __func__, __LINE__, (long)ptr);
    (void)free_type;
    free(ptr);
}

}; // extern "C"

template<typename T>
using c_unique_ptr = std::unique_ptr<T,std::function<void(T*)>>;

template <typename T>
c_unique_ptr<T> make_c_unique(some_c_ops* op, free_type_e free_type)
{
    return c_unique_ptr<T>(static_cast<T*>(calloc(1, sizeof(T))),
                           std::bind(op->free_op, free_type, std::placeholders::_1));
}

void foo(c_unique_ptr<ABC> ptr)
{
    std::cout << __func__ << ":" << __LINE__
        << " ptr=" << reinterpret_cast<size_t>(ptr.get()) <<     std::endl;
}

int main()
{
    some_c_ops ops = { MY_free };
    c_unique_ptr<ABC> ptr = make_c_unique<ABC>(&ops, FREE_ALL);
    std::cout << __func__ << ":" << __LINE__
        << " ptr=" << reinterpret_cast<size_t>(ptr.get()) << std::endl;

    foo(std::move(ptr));

    std::cout << __func__ << ":" << __LINE__
        << " ptr=" << reinterpret_cast<size_t>(ptr.get()) << std::endl;
}

可能な出力:

main:48 ptr=50511440
foo:40 ptr=50511440
MY_free:20 ptr=50511440
main:53 ptr=0
0
Jon Ringle