Boost logo

Boost :

Subject: Re: [boost] [RFC] unique_val (handles, IDs, descriptors...)
From: Andrzej Krzemienski (akrzemi1_at_[hidden])
Date: 2018-02-15 10:18:34


2018-02-14 22:18 GMT+01:00 Miguel Ojeda via Boost <boost_at_[hidden]>:

> Hi all,
>
> While working on a medium-sized project, I had to wrap quite some
> handles, IDs, descriptors, etc. into RAII classes. Somehow, writing
> those and making them movable seemed more verbose than needed. I
> searched in the STL and Boost for something already implemented, but
> nothing seemed to come up. I decided to write my own prototype to see
> whether I was missing something important; but actually using it in my
> project felt quite natural and simple.
>
> At this point, I asked for a second opinion from a well-known expert
> (thanks Scott!) and he agreed that it seemed like a reasonable idea
> but, of course, he would also be surprised if others haven't come up
> with something similar. So I polished it up a bit and uploaded it to:
>
> https://github.com/ojeda/unique_val
>
> Below you have the introduction inlined [1].
>
> If you have the time, please take a look (specially to the Rationale)
> and let me know your comments. The code itself is very short and
> straightforward.
>
> If you already have this class/template in Boost somewhere that I
> missed, please let me know! Otherwise, if you think this could be
> interesting to put into Boost in some existing library (not sure
> which) or as a new tiny library, I would be glad to make the effort to
> expand it, clean it up, etc.
>

So, it is my understanding that the difference between an `int` and an
`unique_val<int>` is that the latter is not copyable (and whoever keeps it
as member is not copyable), and moving from it guarantees that a certain
default value will be assigned to it. Right?

If I got that right, I have two remarks.

1. In your example:

```
class Foo
{
    unique_val<FooHandle> id_;

public:
    Foo() : id_(CreateFoo(/* ... */))
    {
        if (not id_)
            throw std::runtime_error("CreateFoo() failed");
    }

    ~Foo()
    {
        if (id_)
            DestroyFoo(id_.get());
    }

    Foo(Foo&&) = default;
    Foo& operator=(Foo&&) = default;
};
```

`id_` is private (should be of no interest to the users). `Foo` is indeed
non-copyable, but it has not been explicitly declared to the users: it has
only been inferred from the private member (implementation detail). I would
still expect that the class has copy operations explicitly deleted so that
I know it is by design rather than by the current choice of private members.

Your type indeed prevents accidental copying. But at least the example
encourages a bad practice of not declaring the interface of your class
explicitly.

2. Next thing I have to do after defining my `unique_value<>` type is to
write a RAII wrapper for the resource. So, as others mentioned` maybe I
would prefer a tool for doing the latter rather than only a movable ID.
There is a proposal for adding this into the Standard Library:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0052r6.pdf

And also a reference implementation:

https://github.com/PeterSommerlad/SC22WG21_Papers/tree/master/workspace/P0052_scope_exit/src

Regards,
&rzej;


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk