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

C++ 我可以用自定义删除器简洁地声明std::unique_ptr吗?,c++,c++11,unique-ptr,C++,C++11,Unique Ptr,我正在处理的C类型有一个new和free方法关联 new_的类型签名可能会有所不同,但是free_始终是void free_某物(某物*) 目前,我以这种方式声明我的unique\u ptrs,这似乎过于冗长: std::unique_ptr<qdr_link_t, decltype(&free_qdr_link_t)> link{new_qdr_link_t(), free_qdr_link_t}; std::unique_ptr link{new_qdr_link_t(

我正在处理的C类型有一个
new
free
方法关联

new_
的类型签名可能会有所不同,但是
free_
始终是
void free_某物(某物*)

目前,我以这种方式声明我的
unique\u ptr
s,这似乎过于冗长:

std::unique_ptr<qdr_link_t, decltype(&free_qdr_link_t)> link{new_qdr_link_t(), free_qdr_link_t};
std::unique_ptr link{new_qdr_link_t(),free_qdr_link_t};
我能不能少点拘谨?当我的deallocator是位于的
std::free()
函数时,我看到了一个简洁的解决方案。我试图创建一个可以参数化deallocator的版本,但没有成功


我所能想到的最好办法是根据上述声明创建一个宏。

我一直在使用以下命令:

template <auto fptr>
struct Caller {
    template <class... Args>
    auto
    operator()(Args&&... args) noexcept
    {
        return fptr(std::forward<Args...>(args)...);
    }
};
模板
结构调用程序{
模板
汽车
运算符()(Args&&…Args)无异常
{
返回fptr(std::forward(args)…);
}
};
用法示例:

using qdr_freer = Caller<free_qdr_link_t>;

using unique_qdr_ptr = std::unique_ptr<qdr_link_t, qdr_freer>;

[[nodiscard]] unique_qdr_ptr
make_qdr_unique()
{
    return unique_qdr_ptr{new_qdr_link_t()};
}
使用qdr\u freer=调用者;
使用unique_qdr_ptr=std::unique_ptr;
[[nodiscard]]唯一的\u qdr\u ptr
使_qdr_唯一()
{
返回唯一的_qdr_ptr{new_qdr_link_t()};
}
不过,该实现使用了C++17的功能,因此需要进行一些更改才能在C++11中工作



请注意,尽管调用方似乎非常适合
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);
#包括
结构qdr_链接;
qdr_link_t*新的qdr_link_t();
无效自由链接(qdr链接*);
模板
自动生成唯一的ptr(T*raw,Deleter-Deleter)
{
返回std::unique_ptr(原始、删除);
}
//std::unique_ptr link{new_qdr_link_t(),free_qdr_link_t};
自动链接=使链接唯一(新链接(),免费链接);
添加
std::forward
来品尝(如果您愿意的话)



对于C++11,您需要将尾部返回类型
->std::unique_ptr
添加到
make_unique_ptr
,或者将其放在“普通”返回类型中。

固定签名
模板
是一个选项;另一个是
template
。我有多种类似的类型,对于每种类型,我都有一个
type*new\u type(…)
void free\u type(void)
。所以我同意。没有多个名称相同但签名不同的
new\uu,因为它们都是用C声明的,不允许重载。如何
void free\u type(void)
知道释放什么?要释放的东西是否存储在全局中?愚蠢的我,自由函数的签名是
void free\u type(*type)
。很抱歉之前弄错了。就
std::unique\u ptr
的大小而言,这是一个糟糕的软件工程解决方案。每个这样的智能指针都存储一个指向相同函数的指针,这是不必要的。@MaximeGroushkin这就是
unique\u ptr
的工作原理。可以将
free\u qdr\u link\t
包装为某种可调用类型,使其“硬编码”,从而不占用运行时存储。但这里真的需要如此复杂吗?最好的软件工程解决方案是最简单的,除非另外需要。如果一个人使用C++的麻烦,那意味着他们想要一个高效而非简单的解决方案。为了便于解决,他们可以使用Python。@ MaximEgorushkin编写最复杂的解决方案,可能是“效率”不存储单个函数指针,而当你不需要时,不是编写C++的目的。“改用Python”是。。。老实说,这是个愚蠢的建议。如果你坚持这样做,C++只是“麻烦”。至少你必须在某个地方创建一个新的类型来包装
free\u qdr\u link\t
,并且对你拥有的其他每一个free-ing函数也这样做。它的伸缩性不好。如果是这样的话,我会给你看的。在我看来,这种方式在简单性、可读性、可维护性、可用性、性能和可扩展性之间取得了恰当的平衡。