- 可以
std::unique_ptr
只管理指针,还是也可以管理花式指针(类似指针的类型)?
我假设“花哨指针也是如此”,因为对于文件/套接字等资源,花哨指针可能是一个很好的工具。而且似乎没有理由std::unique_ptr
不支持它们。
- 为什么测试托管指针是否为空的方法不一致?
std::unique_ptr
在(GCC)中,有不同的方法来测试托管指针是否为空:
- 在
~unique_ptr()
:(if (__ptr != nullptr)
代码) - 在
reset()
:(if (__old_p)
代码) - 在
operator bool()
:(return get() == pointer() ? false : true;
代码)
问题是它们对指针类型有不同的要求:
bool operator ==(pointer, nullptr_t)
operator bool()
bool operator ==(pointer, pointer)
不一致的用法意味着所有这些都是需要的,但其中一个在语义上就足够了。
#include <memory>
using namespace std;
class File {
FILE * pf_ = nullptr;
public:
File() = default;
File(const char * pathname) { /*...*/ };
void Close() { /*...*/ };
// All are needed to make std::unique_ptr work
explicit operator bool() const { return pf_ == nullptr; }
bool operator ==(nullptr_t) const { return pf_ == nullptr; }
bool operator ==(File) const { /*...*/ return true; };
};
struct FileCloser {
using pointer = File;
void operator ()(File p) const { p.Close(); }
};
int main() {
using FilePtr = unique_ptr<File, FileCloser>;
FilePtr p(File("./abc"));
if(p)
p.reset();
}
恕我直言,std::unique_ptr
应该对指针类型要求最低。一种解决方案是添加静态成员,例如__test_p
,并使用它来一致地测试空性:
template<typename T, typename D = std::default_delete<T>>
class unique_ptr
{
// ...
private:
static constexpr bool __test_p(pointer p) noexcept {
if constexpr (is_convertible_v<pointer, bool>)
return bool(p);
else if constexpr (requires {{ p != nullptr} -> convertible_to<bool>; })
return p != nullptr;
else
return p != pointer();
}
// ...
};
10
最佳答案
1
std::unique_ptr 只能管理指针,还是也可以管理花式指针(类似指针的类型)?
是的
要求std::unique_ptr<T, Deleter>
如下:
-
Deleter
必须是FunctionObject或对FunctionObject 的左值引用或对函数的左值引用,可使用类型参数进行调用unique_ptr<T, Deleter>::pointer
。 -
std::remove_reference_t<Deleter>::pointer
如果存在,则必须满足。
除其他事项外,NullablePointer必须满足您声称不一致的所有三个要求,并且它们必须彼此一致。
为什么测试托管指针是否为空的方法不一致?
拥有“冗余”操作是对约束的用户与约束的实施者的一种权衡,这并不是“错误的”。
虽然确实operator bool
必须等于ptr != nullptr
,并且ptr == nullptr
必须等于,但所有比较都ptr == pointer(nullptr)
采用 和 更符合人体工程学。通过确保每个NullablePointer都可以执行原始指针可以执行的所有操作,可以编写期望原始指针的代码,并且“适用于”花哨的指针。operator bool
恕我直言,std::unique_ptr 应该对指针类型有最低要求。
这是你的意见。委员会另有选择。
1
-
谢谢你的解释!我想如果它是通过concept实现的,那就没那么令人困惑了,尽管我知道它是在concept
unique_ptr
之前引入的。
–
|
File
一个包装FILE *
类型的类。所以只需使用类的析构File
函数即可关闭文件。–
pointer
。–
std::unique_ptr
应该对指针类型有最低要求” – 是的,嗯,你知道,这只是你的看法,伙计。不幸的是,pointer
成员类型必须满足 NullablePointer–
–
File
服务于 2 个主人;首先,它是 的 API 包装器FILE*
,并且它是一个 RAII 管理器。有时您正在使用提供FILE*
您不拥有的 的 C 代码,或者您需要向FILE*
可能拥有所有权的 C 代码提供 ;File
编写的类使这两个操作都更容易。(即,您可以安全地执行File(SOME_FILE_POINTER).Operation()
而无需关闭文件)。然后,唯一的指针File
添加了 RAII 功能。–
|