## Class template unique_resource

boost::scope::unique_resource — RAII wrapper for automatically reclaiming arbitrary resources.

## Synopsis

    // In header: <boost/scope/unique_resource.hpp>

    template<typename Resource, typename Deleter, typename Traits = void>
    class unique_resource {
    public:
      // types
      typedef Resource resource_type;  // Resource type.
      typedef Deleter  deleter_type;   // Deleter type.
      typedef Traits   traits_type;    // Resource traits.

      // construct/copy/destruct
      unique_resource() noexcept(...);
      template<typename D> unique_resource(default_resource_t, D &&) noexcept(...);
      template<typename R> explicit unique_resource(R &&) noexcept(...);
      template<typename R, typename D> unique_resource(R &&, D &&) noexcept(...);
      unique_resource(unique_resource const &) = delete;
      unique_resource(unique_resource &&) noexcept(...);
      unique_resource & operator=(unique_resource const &) = delete;
      unique_resource & operator=(unique_resource &&) noexcept(...);
      ~unique_resource() noexcept(...);

      // public member functions
      explicit operator bool() const noexcept;
      bool allocated() const noexcept;
      resource_type const & get() const noexcept;
      deleter_type const & get_deleter() const noexcept;
      void release() noexcept;
      void reset() noexcept(...);
      template<typename R> void reset(R &&) noexcept(...);
      resource_type const & operator->() const noexcept;
      auto operator*() const noexcept(...);
      void swap(unique_resource &) noexcept(...);

      // friend functions
      void swap(unique_resource &, unique_resource &) noexcept(...);
    };

## Description

A `unique_resource` object exclusively owns wrapped resource and invokes the deleter function object on it on destruction. The wrapped resource can have any type that is:

- Move-constructible, where the move constructor is marked as `noexcept`, or

- Copy-constructible, or

- An lvalue reference to an object type.

The deleter must be a function object type that is callable on an lvalue of the resource type. The deleter must be copy-constructible.

An optional resource traits template parameter may be specified. Resource traits can be used to optimize `unique_resource` implementation when the following conditions are met:

- There is at least one value of the resource type that is considered unallocated (that is, no allocated resource shall be equal to one of the unallocated resource values). The unallocated resource values need not be deallocated using the deleter.

- One of the unallocated resource values can be considered the default. Constructing the default resource value and assigning it to a resource object (whether allocated or not) shall not throw exceptions.

- Resource objects can be tested for being unallocated. Such a test shall not throw exceptions.

If specified, the resource traits must be a class type that has the following public static members:

- `R make_default() noexcept` - must return the default resource value such that `std::is_constructible< Resource, R >::value && std::is_nothrow_assignable< Resource&, R >::value` is `true`.

- `bool is_allocated(Resource const& res) noexcept` - must return `true` if `res` is not one of the unallocated resource values and `false` otherwise.

Note that `is_allocated(make_default())` must always return `false`.

When resource traits satisfying the above requirements are specified, `unique_resource` will be able to avoid storing additional indication of whether the owned resource object needs to be deallocated with the deleter on destruction. It will use the default resource value to initialize the owned resource object when `unique_resource` is not in the allocated state. Additionally, it will be possible to construct `unique_resource` with unallocated resource values, which will create `unique_resource` objects in unallocated state (the deleter will not be called on unallocated resource values).

### Template Parameters

1.     typename Resource

   Resource type.

2.     typename Deleter

   Resource deleter function object type.

3.     typename Traits = void

   Optional resource traits type.

### `unique_resource` public construct/copy/destruct

1.     unique_resource() noexcept(...);

   Constructs an unallocated unique resource guard.

   Requires: Default `Resource` value can be constructed. `Deleter` is default-constructible and is not a pointer to function.

   Effects: Initializes the `Resource` object with the default resource value. Default-constructs the `Deleter` object.

   Throws: Nothing, unless construction of `Resource` or `Deleter` throws.

   Postconditions: | `this->allocated() == false`

2.     template<typename D>
         unique_resource(default_resource_t res, D && del) noexcept(...);

   Constructs an unallocated unique resource guard with the given deleter.

   Requires: Default `Resource` value can be constructed and `Deleter` is constructible from del.

   Effects: Initializes the `Resource` value with the default resource value. If `Deleter` is nothrow constructible from `D&&` then constructs `Deleter` from `std::forward< D >(del)`, otherwise constructs from `del`.

   Throws: Nothing, unless construction of `Resource` or `Deleter` throws.

   Parameters:

   `del` | Resource deleter function object.
   `res` | A tag argument indicating default resource value.

   Postconditions: | `this->allocated() == false`

3.     template<typename R> explicit unique_resource(R && res) noexcept(...);

   Constructs a unique resource guard with the given resource and a default-constructed deleter.

   Requires: `Resource` is constructible from res. `Deleter` is default-constructible and is not a pointer to function.

   Effects: Constructs the unique resource object as if by calling ``unique_resource`(std::forward< R >(res), Deleter())`.

   Throws: Nothing, unless construction of `Resource` or `Deleter` throws.

   Parameters:

   `res` | Resource object.

4.     template<typename R, typename D>
         unique_resource(R && res, D && del) noexcept(...);

   Constructs a unique resource guard with the given resource and deleter.

   Requires: `Resource` is constructible from res and `Deleter` is constructible from del.

   Effects: If `Resource` is nothrow constructible from `R&&` then constructs `Resource` from `std::forward< R >(res)`, otherwise constructs from `res`. If `Deleter` is nothrow constructible from `D&&` then constructs `Deleter` from `std::forward< D >(del)`, otherwise constructs from `del`.

   If construction of `Resource` or `Deleter` throws and res is not an unallocated resource value, invokes del on res (if `Resource` construction failed) or the constructed `Resource` object (if `Deleter` construction failed).

   Throws: Nothing, unless construction of `Resource` or `Deleter` throws.

   Parameters:

   `del` | Resource deleter function object.
   `res` | Resource object.

   Postconditions: | If res is an unallocated resource value then `this->allocated() == false`, otherwise `this->allocated() == true`.

5.     unique_resource(unique_resource const &) = delete;

6.     unique_resource(unique_resource && that) noexcept(...);

   Move-constructs a unique resource guard.

   Requires: `Resource` and `Deleter` are move-constructible.

   Effects: If `Resource` is nothrow move-constructible then move-constructs `Resource`, otherwise copy-constructs. If `Deleter` is nothrow move-constructible then move-constructs `Deleter`, otherwise copy-constructs. Deactivates the moved-from unique resource object.

   If an exception is thrown during construction, that is left in its original state.

   | Note
   This logic ensures that in case of exception the resource is not leaked and remains owned by the move source.

   Throws: Nothing, unless construction of `Resource` or `Deleter` throws.

   Parameters:

   `that` | Move source.

   Postconditions: | Let `allocated` be equal to `that.allocated()` prior to the operation. Then `this->allocated() == allocated` and `that.allocated() == false`.

7.     unique_resource & operator=(unique_resource const &) = delete;

8.     unique_resource & operator=(unique_resource && that) noexcept(...);

   Move-assigns a unique resource guard.

   Requires: `Resource` and `Deleter` are move-assignable.

   Effects: Calls `this->reset()`. Then, if `Deleter` is nothrow move-assignable, move-assigns the `Deleter` object first and the `Resource` object next. Otherwise, move-assigns the objects in reverse order. Lastly, deactivates the moved-from unique resource object.

   If an exception is thrown, that is left in its original state.

   | Note
   The different orders of assignment ensure that in case of exception the resource is not leaked and remains owned by the move source.

   Throws: Nothing, unless assignment of `Resource` or `Deleter` throws.

   Parameters:

   `that` | Move source.

   Postconditions: | Let `allocated` be equal to `that.allocated()` prior to the operation. Then `this->allocated() == allocated` and `that.allocated() == false`.

9.     ~unique_resource() noexcept(...);

   If the resource is allocated, calls the deleter function on it. Destroys the resource and the deleter.

   Throws: Nothing, unless invoking the deleter throws.

### `unique_resource` public member functions

1.     explicit operator bool() const noexcept;

   Returns `true` if the resource is allocated and to be reclaimed by the deleter, otherwise `false`.

   | Note
   This method does not test the value of the resource.

   Throws: Nothing.

2.     bool allocated() const noexcept;

   Returns `true` if the resource is allocated and to be reclaimed by the deleter, otherwise `false`.

   Throws: Nothing.

3.     resource_type const & get() const noexcept;

   Returns a reference to the resource object.

   Throws: Nothing.

4.     deleter_type const & get_deleter() const noexcept;

   Returns a reference to the deleter object.

   Throws: Nothing.

5.     void release() noexcept;

   Marks the resource as unallocated. Does not call the deleter if the resource was previously allocated.

   Throws: Nothing.

   Postconditions: | `this->allocated() == false`

6.     void reset() noexcept(...);

   If the resource is allocated, calls the deleter function on it and marks the resource as unallocated.

   Throws: Nothing, unless invoking the deleter throws.

   Postconditions: | `this->allocated() == false`

7.     template<typename R> void reset(R && res) noexcept(...);

   Assigns a new resource object to the unique resource wrapper.

   Effects: Calls `this->reset()`. Then, if `Resource` is nothrow assignable from `R&&`, assigns `std::forward< R >(res)` to the stored resource object, otherwise assigns `res`.

   If res is not an unallocated resource value and an exception is thrown during the operation, invokes the stored deleter on res before returning with the exception.

   Throws: Nothing, unless invoking the deleter throws.

   Parameters:

   `res` | Resource object to assign.

   Postconditions: | `this->allocated() == false`

8.     resource_type const & operator->() const noexcept;

   Invokes indirection on the resource object.

   Requires: `Resource` is dereferenceable.

   Effects: Returns a reference to the resource object as if by calling `get()`.

   | Note
   If `Resource` is not a pointer type, the compiler will invoke its `operator->`. Such call sequence will continue until a pointer is obtained.

   Throws: Nothing. Note that any implicit subsequent calls to other `operator->` functions that are caused by this call may have different throw conditions.

9.     auto operator*() const noexcept(...);

   Dereferences the resource object.

   Requires: `Resource` is dereferenceable.

   Effects: Returns the result of dereferencing the resource object as if by calling `*get()`.

   Throws: Nothing, unless dereferencing the resource object throws.

10.     void swap(unique_resource & that) noexcept(...);

    Swaps two unique resource wrappers.

    Requires: `Resource` and `Deleter` are swappable. At least one of `Resource` and `Deleter` is nothrow swappable.

    Effects: Swaps the resource objects and deleter objects stored in `*this` and that as if by calling unqualified `swap` in a context where `std::swap` is found by overload resolution.

    If an exception is thrown, and the failed swap operation supports strong exception guarantee, both `*this` and that are left in their original states.

    Throws: Nothing, unless swapping the resource objects or deleters throw.

    Parameters:

    `that` | Unique resource wrapper to swap with.

### `unique_resource` friend functions

1.     void swap(unique_resource & left, unique_resource & right) noexcept(...);

   Swaps two unique resource wrappers.

   Effects: As if `left.swap(right)`.