std::unique_ptr 支持花式指针吗?

问题描述 投票:0回答:1
  • 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();
}

https://godbolt.org/z/fjPjWzzhW

恕我直言,

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();
    }
// ...
};
c++ c++11 gcc unique-ptr
1个回答
0
投票

std::unique_ptr<T, Deleter>
的要求是:

  • Deleter
    必须是 FunctionObject 或对 FunctionObject 的左值引用或对函数的左值引用,可使用类型为
    unique_ptr<T, Deleter>::pointer
    的参数进行调用。

  • std::remove_reference_t<Deleter>::pointer
    ,如果存在,必须满足NullablePointer

除其他事项外,NullablePointer 必须满足您声称等效的所有三个要求,并且它们必须彼此一致。

不一致的用法意味着所有这些都是必需的,而其中一个在语义上就足够了。

您无法从

bool operator ==(pointer, std::nullptr_t)
合成
bool operator ==(pointer, pointer)
,反之亦然。不相等的非空指针必须是可区分的。

拥有“冗余”操作是有利于约束的用户与约束的实现者的权衡,这并不是“错误”。

虽然

operator bool
确实必须等同于
ptr != nullptr
,但拥有
operator bool
更符合人体工程学,因为这允许
if(ptr)

© www.soinside.com 2019 - 2024. All rights reserved.