开发者

unique_ptr custom storage type example?

Howard Hinnant explained that unique_ptr can also use a custom storage type. He mentions as an example "shared memory".

He only gives the rough idea (which is fine for a quick intro). But can anyone complete his example for a "custom storage type" (be it shared memory or not)?

To support placing unique_ptr into shared memory, the custom deleter can contain a custom pointer type (typically not a real pointer in shared memory applications). One simply places a nested type called pointer which emulates pointer behavior within your deleter, publicly accessible:

template <class T>
class MyDeleter
{
public:
    class pointer
    {
     public:
        friend bool operator==(pointer x, poin开发者_如何转开发ter y);
        friend bool operator!=(pointer x, pointer y);
        // ...
    };

    void operator()(pointer p);
};

void test()
{
    unique_ptr<int, MyDeleter<int> > p;
    MyDeleter<int>::pointer p2 = p.get();  // A custom pointer type used for storage
}

I suspect that // ... must be extended, and test() will probably do some additional things in a real "custom storage type" example.

Can someone tell me where he/she

  • has actually already used this customization,
  • and in that context,
  • which what customization code, (at //... probably)
  • and how client code uses it? (at test() probably)


You might be interested in boost::offset_ptr which served as the motivating use case for this customization point in unique_ptr. offset_ptr is a fully developed pointer type which could be installed into a custom deleter using a simple typedef. Its use case is to put unique_ptr into shared memory.


20.7.1.2/3 tells us

The type unique_ptr<T, D>::pointer shall satisfy the requirements of NullablePointer (17.6.3.3).

According to 17.6.3.3, given a type P, these requirements are:

  • P is EqualityComparable, DefaultConstructible, CopyConstructible, CopyAssignable, and Destructible
  • Lvalues of P are swappable
  • Value-initializing an object of type P produces the null value of the type, and the null value shall be equivalent only to itself
  • An object of type P can be contextually converted to bool
  • An object of type P can be initialized with and assigned nullptr, and this produces the null value
  • An object of type P can be equality compared to nullptr, and the comparison is true if and only if the object has the null value
  • None of the required operations may throw (but need no explicit noexcept or throw())

Note specifically that operator* and operator-> are not actually required. Also note that the builtin numeric types satisfy all the requirements except nullptr initialization/assignment.

For example, the following type should fulfill all the requirements:

class handle {
    int id;
  public:
    // default and nullptr constructors folded together
    handle(std::nullptr_t = nullptr) : id(0) { }

    explicit operator bool() { return l.id != 0; }

    friend bool operator ==(handle l, handle r) { return l.id == r.id; }
    friend bool operator !=(handle l, handle r) { return !(l == r); }

    // default copy ctor and operator= are fine

    // explicit nullptr assignment and comparison unneeded
    // because of implicit nullptr constructor

    // swappable requirement fulfilled by std::swap
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜