On Sun, Jun 16, 2019 at 7:30 AM Zach Laine via Boost-users <boost-users@lists.boost.org> wrote:
>
> Dear Boost community,
>
> The formal review of JeanHeyd Meneide's out_ptr library starts Sunday, June 16th
> and ends on Wednesday, June 26th.

Not yet a review, more like initial thoughts and questions.

I've always used shared_ptr to wrap all kinds of "handles" to objects, including IUnknown and HANDLE on Windows, but even things like OpenGL unsigned int handles. It would be really nice to support such non-pointer handle types, so my initial reaction is that out_ptr doesn't go far enough.

To clarify what I mean by non-pointer handle types, consider that it makes sense to keep an OpenGL shader alive by a shared_ptr<unsigned const>, even though the OpenGL handle itself is an unsigned int, not a pointer. To this end I use the following helper function make_handle, which takes a non-pointer handle and a deleter function, and returns a shared_ptr:

namespace handle_detail
{
  template <class H, class D>
  struct deleter
  {
    deleter( H h, D d ):
      h_(h),
      d_(d)
    {
    }

    void operator()( H * h )
    {
      assert(!h);
      (void) d_(h_);
    }

    H h_;
    D d_;
  };
}

template <class H,class D>
std::shared_ptr<H const> make_handle( H h, D d )
{
  std::shared_ptr<H> p((H *)0,handle_detail::deleter<H,D>(h,d));
  return std::shared_ptr<H const>(
    p,
    &std::get_deleter<handle_detail::deleter<H,D> >(p)->h_ );
}

Then I write a wrapper function for glCreateShader:

std::shared_ptr<unsigned const> CreateShader( unsigned shaderType )
{
  assert(!glGetError());
  if( unsigned s=glCreateShader(shaderType) )
  {
    if( unsigned err=glGetError_() )
      throw ....;
    return make_handle(s,glDeleteShader);
  }
  else
    throw zero_handle_detected();
}

Which in the end is used like this:

std::shared_ptr<unsigned const> sh = CreateShader(GL_VERTEX_SHADER);

As you can see the CreateShader wrapper is verbose and clunky, but easy to use. It would be nice to be able to automate that.

(By the way, it never crossed my mind to pass the shared_ptr, like it is done in out_ptr, instead of returning it. One problem with passing it as an argument is that it makes it impossible to use in a constructor initializer list.)

Which leads to my questions:

- Is it possible for out_ptr to support returning the shared_ptr instead of taking it as an argument?

- Is it possible to support non-pointer handle types as well?

- Can error handling be incorporated? I realize there are different options, but perhaps only two need to be supported: a result<T> of some sort (such types' interfaces are somewhat standard much like smart pointer interfaces are) or throw an exception.