提问者:小点点

我可以用自定义删除器简洁地声明std::unique_ptr吗?


我处理的是与new_free_方法相关联的C类型。

new_的类型签名可能不同,但free_始终是void free_something(something*);

目前,我以这种方式声明我的unique_ptrs,这似乎过于冗长:

std::unique_ptr<qdr_link_t, decltype(&free_qdr_link_t)> link{new_qdr_link_t(), free_qdr_link_t};

我能不能少点礼节?我在https://stackoverflow.com/a/43626234/1047788上看到了一个简洁的解决方案,用于解决我的deallocator是std::free()函数的情况。我试图创建一个可以参数化deallocator的版本,但没有任何结果。

我能想到的最好的办法是从上面的声明中创建一个宏。


共2个答案

匿名用户

我一直在使用以下方法:

template <auto fptr>
struct Caller {
    template <class... Args>
    auto
    operator()(Args&&... args) noexcept
    {
        return fptr(std::forward<Args...>(args)...);
    }
};

示例用法:

using qdr_freer = Caller<free_qdr_link_t>;

template<class T>
using unique_qdr_ptr = std::unique_ptr<T, qdr_freer>;

template<class T>
[[nodiscard]] unique_qdr_ptr<T>
make_qdr_unique() noexcept
{
    return unique_qdr_ptr<T>{new_qdr_link_t()};
}

但是这个实现使用了C++17的特性,因此需要做一些更改才能在C++11中工作。

请注意,严格地说,caller没有很好地定义为与std:free一起使用,std:free是一个没有指定为“可寻址”的标准库函数。

匿名用户

让语言来做艰苦的工作吧!

#include <memory>

struct qdr_link_t;
qdr_link_t* new_qdr_link_t();
void free_qdr_link_t(qdr_link_t*);

template <typename T, typename Deleter>
auto make_unique_ptr(T* raw, Deleter deleter)
{
    return std::unique_ptr<T, Deleter>(raw, deleter);
}

//std::unique_ptr<qdr_link_t, decltype(&free_qdr_link_t)> link{new_qdr_link_t(), free_qdr_link_t};
auto link = make_unique_ptr(new_qdr_link_t(), free_qdr_link_t);

添加std::forward到taste(如果您关心的话)。

对于C++11,您需要添加尾随返回类型->;std::unique_ptr转换为make_unique_ptr,或者只是将其放在“normal”返回类型中。