out_ptr's formal review starts now!

Dear Boost community, The formal review of JeanHeyd Meneide's out_ptr library starts Sunday, June 16th and ends on Wednesday, June 26th. out_ptr is a library for making it easy to interoperate between smart pointers and traditional C-style initialization and allocation interfaces. It also enables doing so in a way that allows library authors to opt into speed optimizations for their smart pointers that give them performance equivalent to typical C pointers (see benchmarks ( https://github.com/ThePhD/out_ptr/blob/master/docs/out_ptr/benchmarks.adoc) and the Standard C++ proposal for more details). Online docs can be found here: https://github.com/ThePhD/out_ptr/blob/master/docs/out_ptr.adoc The GitHub repository is available here: https://github.com/ThePhD/out_ptr Also, there is an associated standards proposal: https://thephd.github.io/vendor/future_cxx/papers/d1132.html We encourage your participation in this review. At a minimum, please state: - Whether you believe the library should be accepted into Boost - Your name - Your knowledge of the problem domain You are strongly encouraged to also provide additional information: - What is your evaluation of the library's: * Design * Implementation * Documentation * Tests * Usefulness - Did you attempt to use the library? If so: * Which compiler(s)? * What was the experience? Any problems? - How much effort did you put into your evaluation of the review? All issues discussed during this review will be tracked on the library's GitHub issue tracker at https://github.com/ThePhD/out_ptr/issues. Regards, Zach Laine

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.

On Mon, Jun 24, 2019 at 5:55 PM Emil Dotchevski via Boost-users < boost-users@lists.boost.org> wrote:
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.
Sorry for the overquoting; I'm adding JenHeyd (the author), so he can easily share the context here. He was not subscribed to boost-users previously. Zach

On Mon, Jun 24, 2019 at 7:49 PM Zach Laine <whatwasthataddress@gmail.com> wrote:
Sorry for the overquoting; I'm adding JenHeyd (the author), so he can easily share the context here. He was not subscribed to boost-users previously.
His name is actually spelled "JeanHeyd". Sorry for the confusion. Stupid keybords. Zach

Dear Emil Dotchevski, Thank you for your inquiry. Regarding your questions... - Is it possible for out_ptr to support returning the shared_ptr instead of
taking it as an argument?
That's not the purpose of this library. This library is to interoperate with pre-existing functions whose interfaces you don't have control of or that can't be brought into the wonderful world of C++: if you had control, you could just -- as you have done with your code -- write a wrapper. The problem is that writing wrappers continually does not scale, and it is very hard to automate that kind of boilerplate until we get the Reflection TS / Static Reflection in C++. This library does not aim to try to write a whole new Boost.Preprocessor based, orfunction-signature-reflection-and-conversion library. That is a massive undertaking, and far beyond the scope of this library. - Is it possible to support non-pointer handle types as well?
It already supports non-pointer handle types, because you can specify the pointer type explicitly. We have examples for out_ptr<void*>, but nothing is stopping you from doing out_ptr<int>. I frequently use this in C Style APIs which work with integers. Here is an example of using `int` representing a "file descriptor" with unique_ptr: https://github.com/ThePhD/out_ptr/blob/master/examples/source/std.custom_uni... out_ptr and inout_ptr work out-of-the-box with custom handle types and unique_resource, for example. The following example has a specialization only because it wants to gain the special performance-enhancing properties: but the interface of the handle class in the example is perfectly adequate on its own without the written customization point: https://github.com/ThePhD/out_ptr/blob/master/examples/source/custom.handle.... - 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.
Since it works with the typical C-style of pointer output parameters, no. If somebody worked on some new, cool library doing some of what I outlined in the answer to your first question: maybe! Sincerely, JeanHeyd Meneide
participants (3)
-
Emil Dotchevski
-
JeanHeyd Meneide
-
Zach Laine