Adding polymorphic_value to boost
I'd like to propose adding the class-template `polymorphic_value` to boost. `polymorphic_value` is designed to allow the compiler to correctly generate special member functions for classes with polymorphic components (It's `any` with an interface). `polymorphic_value` has been proposed for standardisation in P0201 and has advanced through the Library Evolution group in Albuquerque (Nov 5-10). https://wg21.link/p0201 A working draft of the proposal and implementation can be found at https://github.com/jbcoe/polymorphic_value I gave a presentation about polymorphic_value at C++::London here: https://skillsmatter.com/skillscasts/9539-a-polymorphic-value-type-for-c-plu... Matt Calabrese has kindly offered to be review manager. Kind regards, Jon
On Thu, Nov 16, 2017 at 3:14 AM, Jonathan Coe via Boost < boost@lists.boost.org> wrote:
I'd like to propose adding the class-template `polymorphic_value` to boost.
`polymorphic_value` is designed to allow the compiler to correctly generate special member functions for classes with polymorphic components (It's `any` with an interface).
`polymorphic_value` has been proposed for standardisation in P0201 and has advanced through the Library Evolution group in Albuquerque (Nov 5-10). https://wg21.link/p0201
A working draft of the proposal and implementation can be found at https://github.com/jbcoe/polymorphic_value
I gave a presentation about polymorphic_value at C++::London here: https://skillsmatter.com/skillscasts/9539-a-polymorphic-value-type-for-c- plus-plus
Matt Calabrese has kindly offered to be review manager.
Not only do I want to see this put forth for review, but I'd also like to see its review fast-tracked, since it's a target for standardization currently being examined by LEWG. There are a few of us in LEWG that want to see essentially *all* novel library submissions do through Boost or another widely-used library. Mostly you can find these people on this list. :) This is why Boost was initially created, after all. Whether it passes review without change, gets rejected, or anything in between, the process will be very informative to LEWG. Zach
On Fri, Nov 17, 2017 at 4:36 PM, Zach Laine via Boost wrote: Not only do I want to see this put forth for review, but I'd also like to
see its review fast-tracked, since it's a target for standardization
currently being examined by LEWG. There are a few of us in LEWG that want
to see essentially *all* novel library submissions do through Boost or
another widely-used library. Mostly you can find these people on this
list. :) This is why Boost was initially created, after all. Whether it passes
review without change, gets rejected, or anything in between, the process
will be very informative to LEWG. +1
--Beman
-----Original Message----- From: Boost [mailto:boost-bounces@lists.boost.org] On Behalf Of Zach Laine via Boost Sent: 17 November 2017 21:37 To: boost@lists.boost.org Cc: Zach Laine Subject: Re: [boost] Adding polymorphic_value to boost
On Thu, Nov 16, 2017 at 3:14 AM, Jonathan Coe via Boost < boost@lists.boost.org> wrote:
I'd like to propose adding the class-template `polymorphic_value` to boost.
`polymorphic_value` is designed to allow the compiler to correctly generate special member functions for classes with polymorphic components (It's `any` with an interface).
`polymorphic_value` has been proposed for standardisation in P0201 and has advanced through the Library Evolution group in Albuquerque (Nov 5-10). https://wg21.link/p0201
A working draft of the proposal and implementation can be found at https://github.com/jbcoe/polymorphic_value
I gave a presentation about polymorphic_value at C++::London here: https://skillsmatter.com/skillscasts/9539-a-polymorphic-value-type-for-c- plus-plus
Matt Calabrese has kindly offered to be review manager.
Not only do I want to see this put forth for review, but I'd also like to see its review fast-tracked,
+1 Paul
On 11/18/17 00:36, Zach Laine via Boost wrote:
On Thu, Nov 16, 2017 at 3:14 AM, Jonathan Coe via Boost < boost@lists.boost.org> wrote:
I'd like to propose adding the class-template `polymorphic_value` to boost.
`polymorphic_value` is designed to allow the compiler to correctly generate special member functions for classes with polymorphic components (It's `any` with an interface).
`polymorphic_value` has been proposed for standardisation in P0201 and has advanced through the Library Evolution group in Albuquerque (Nov 5-10). https://wg21.link/p0201
A working draft of the proposal and implementation can be found at https://github.com/jbcoe/polymorphic_value
I gave a presentation about polymorphic_value at C++::London here: https://skillsmatter.com/skillscasts/9539-a-polymorphic-value-type-for-c- plus-plus
Matt Calabrese has kindly offered to be review manager.
Not only do I want to see this put forth for review, but I'd also like to see its review fast-tracked, since it's a target for standardization currently being examined by LEWG.
Not knowing anything about `polymorphic_value`, I welcome a new library submitted for a review, but I don't see why the review should be fast-tracked. Fast-tracked reviews are typically performed on something that the community is very familiar with (not only the concept but the implementation as well), which basically means it has to undergo a full review first. That the library is also being reviewed by someone else (e.g. LEWG) does not mean it has a free entry into Boost.
On Sat, Nov 18, 2017 at 11:11 AM, Andrey Semashev via Boost < boost@lists.boost.org> wrote:
On 11/18/17 00:36, Zach Laine via Boost wrote:
Not only do I want to see this put forth for review, but I'd also like to see its review fast-tracked, since it's a target for standardization currently being examined by LEWG.
Not knowing anything about `polymorphic_value`, I welcome a new library submitted for a review, but I don't see why the review should be fast-tracked. Fast-tracked reviews are typically performed on something that the community is very familiar with (not only the concept but the implementation as well), which basically means it has to undergo a full review first. That the library is also being reviewed by someone else (e.g. LEWG) does not mean it has a free entry into Boost.
Agreed. What I meant by fast-tracked wasn't that it should be reviewed differently, but that the review should happen sooner. Zach
On Sat, Nov 18, 2017 at 10:29 AM, Zach Laine via Boost
differently, but that the review should happen sooner.
Let us be specific. Do you mean that the review should happen soon enough that it has a chance of going in to Boost 1.67.0 if it passes? Or 1.68.0? Thanks
On Sat, Nov 18, 2017 at 1:12 PM, Vinnie Falco via Boost < boost@lists.boost.org> wrote:
On Sat, Nov 18, 2017 at 10:29 AM, Zach Laine via Boost
wrote: What I meant by fast-tracked wasn't that it should be reviewed differently, but that the review should happen sooner.
Let us be specific. Do you mean that the review should happen soon enough that it has a chance of going in to Boost 1.67.0 if it passes? Or 1.68.0?
Let us be less specific. Sometime in the next 3 to 9 months would be timely enough for me (others, please feel free to correct me on this range). Just not the 2 years that some things have sat in the review queue. Zach
On Sun, Nov 19, 2017 at 1:46 PM, Zach Laine wrote:
Let us be less specific. Sometime in the next 3 to 9 months would be timely enough for me (others, please feel free to correct me on this range). Just not the 2 years that some things have sat in the review queue.
The review schedule is currently empty, so there's no obstacle to having the review scheduled as soon as they want - even early as December. As long as the review manager is on board, and the author has communicated the period that they want to the review wizard, etc. Glen
On 18 November 2017 at 17:11, Andrey Semashev via Boost < boost@lists.boost.org> wrote:
Not knowing anything about `polymorphic_value`, I welcome a new library submitted for a review, but I don't see why the review should be fast-tracked. Fast-tracked reviews are typically performed on something that the community is very familiar with (not only the concept but the implementation as well), which basically means it has to undergo a full review first. That the library is also being reviewed by someone else (e.g. LEWG) does not mean it has a free entry into Boost.
This sort of thing has been discussed many times on this list already, under the name clone_ptr. I would expect many people to be familiar with it.
On 21 Nov 2017, at 09:32, Mathias Gaunard via Boost
wrote: On 18 November 2017 at 17:11, Andrey Semashev via Boost < boost@lists.boost.org> wrote:
Not knowing anything about `polymorphic_value`, I welcome a new library submitted for a review, but I don't see why the review should be fast-tracked. Fast-tracked reviews are typically performed on something that the community is very familiar with (not only the concept but the implementation as well), which basically means it has to undergo a full review first. That the library is also being reviewed by someone else (e.g. LEWG) does not mean it has a free entry into Boost.
This sort of thing has been discussed many times on this list already, under the name clone_ptr. I would expect many people to be familiar with it.
Thanks Matthias, Is there a way we can search the archives for the old discussion? Regards Jon
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
On 21 November 2017 at 10:50, Jonathan Coe
Thanks Matthias,
Is there a way we can search the archives for the old discussion?
Regards
Jon
Here are a few I've found https://lists.boost.org/Archives/boost/2000/03/2696.php (2000) https://lists.boost.org/Archives/boost/2007/09/126982.php (2007) https://lists.boost.org/Archives/boost/2010/05/166647.php (2010)
Mathias Gaunard wrote:
On 21 November 2017 at 10:50, Jonathan Coe
wrote: Thanks Matthias,
Is there a way we can search the archives for the old discussion?
...
Here are a few I've found
https://lists.boost.org/Archives/boost/2000/03/2696.php (2000) https://lists.boost.org/Archives/boost/2007/09/126982.php (2007) https://lists.boost.org/Archives/boost/2010/05/166647.php (2010)
The earliest deep-copy pointer is Alan Griffiths's grin_ptr:
http://web.archive.org/web/20110907102434/http://www.octopull.demon.co.uk/ar...
It's "grin_ptr" because Pimpl was known as Chesire's Cat in those days for
some reason.
My own impl_ptr from 2001 can be found here:
http://pdimov.com/cpp2/impl_ptr.zip
Again, impl_ptr because its primary purpose is to implement the Pimpl idiom,
but in that same archive there's a variant<T> class which is a polymorphic
value.
(Both Pimpl and polymorphic values need const propagation.)
A copying pointer has been re-proposed repeatedly, but it didn't take.
Polymorphic values also didn't become very popular, perhaps because in C++03
when you push_back one into a vector you pay dearly in reallocations. This
pushes one towards implementing copy-on-write, for which shared_ptr is
better suited, or often you're even fine with vector
Le 16/11/2017 à 10:14, Jonathan Coe via Boost a écrit :
I'd like to propose adding the class-template `polymorphic_value` to boost.
`polymorphic_value` is designed to allow the compiler to correctly generate special member functions for classes with polymorphic components (It's `any` with an interface).
`polymorphic_value` has been proposed for standardisation in P0201 and has advanced through the Library Evolution group in Albuquerque (Nov 5-10). https://wg21.link/p0201
A working draft of the proposal and implementation can be found at https://github.com/jbcoe/polymorphic_value
I gave a presentation about polymorphic_value at C++::London here: https://skillsmatter.com/skillscasts/9539-a-polymorphic-value-type-for-c-plu...
Matt Calabrese has kindly offered to be review manager.
Hi Jonathan, I'll be all for having `polymorphic_value` in Boost so that we can play with this class. However, I would like to see also your original `cloning_ptr` and the `propagate_const` and see how `polymorphic_value` can be built on top of these classes. This will be the occasion to prove what you said in your paper p0201r2 ;-) Of course, we can review `polymorphic_value` independnetly of `cloning_ptr` and the `propagate_const`. "Design changes from cloned_ptr The design of polymorphic_value is based upon cloned_ptr after advice from LEWG. The authors would like to make LEWG explicitly aware of the cost of these design changes. polymorphic_value has value-like semantics: copies are deep and const is propagated to the owned object. The first revision of this paper presented cloned_ptr which had mixed pointer/value semantics: copies are deep but const is not propagated to the owned object. polymorphic_value can be built from cloned_ptr and propagate_const but there is no way to remove const propagation from polymorphic_value. As polymorphic_value is a value, dynamic_pointer_cast, static_pointer_cast and const_pointer_cast are not provided. If a polymorphic_value is constructed with a custom copier or deleter, then there is no way for a user to implement the cast operations provided for cloned_ptr. [Should we be standardizing vocabulary types (optional, variant and polymorphic_value) or components through which vocabulary types can be trivially composed (propagate_const, cloned_ptr)?]" Best, Vicente
On 11/16/17 1:14 AM, Jonathan Coe via Boost wrote:
I'd like to propose adding the class-template `polymorphic_value` to boost.
`polymorphic_value` is designed to allow the compiler to correctly generate special member functions for classes with polymorphic components (It's `any` with an interface).
`polymorphic_value` has been proposed for standardisation in P0201 and has advanced through the Library Evolution group in Albuquerque (Nov 5-10). https://wg21.link/p0201
A working draft of the proposal and implementation can be found at https://github.com/jbcoe/polymorphic_value
I gave a presentation about polymorphic_value at C++::London here: https://skillsmatter.com/skillscasts/9539-a-polymorphic-value-type-for-c-plu...
Matt Calabrese has kindly offered to be review manager.
Kind regards,
Jon
I looked over the github repo and the standards proposals. I also looked over the posts in this thread. I'm thinking the the enthusiasm is a little premature. Just some random observations which occurred to me as I looked this over. Explanation =========== From looking at the proposed implementation and one small sentence: "A polymorphic_value<T> may hold a an object of a class publicly derived from T" which suggests to me that certain operations such as assigment, copy, operators? etc. could be used with different instances created with different types all derived from type T. Sort of like a variant whose underlying types is that set of types derived from T. I don't know if I got this right - but reading the text and looking at the code, this is the impression I get. If I got it wrong, there are only really two possibilities: a) I'm stupid b) The explanation/motivation isn't rich enough. Just for the sake of argument, let's suppose that b) is the correct one. The motivating case seems to be usage as constituent of a composite object. But this seems to me totally unrelated to the interesting features of the "polymorphic value_type". I can't see why it's included or what it shows. So I would like to see some examples of problems that this would solve and how it would solve them. I would also like to see summary reference including valid expressions and type requirements on the type T parameter. Tests ===== Looks OK - but I'd have to invest more effort to be sure. Source Code =========== OK - I'm nit picking here. I found the extensive usage of white space meant that I could only display about 20 lines of my code on my monitor. I would have found less blank lines and more {} added to other lines a big help in being able to read the code. I don't want for this to go on a tangent which ends up at the tabs/spaces cul-de-sac. So don't feel the need to respond to this. Soooooooo - In my humble opinion, this submission needs more work before it could seriously considered for review as a boost library. Robert Ramey
Soooooooo - In my humble opinion, this submission needs more work before it could seriously considered for review as a boost library.
To offer a quick alternative view, my immediate impression upon reading p0201 paper, was "ah cool, someone's finally formalizing why I've used pImpl for more than a decade" i.e. "value-izing" a polymorphic hierarchy. Making things a value type is very useful - coping and moving just "do as the ints do" and so make them easy to use in contexts like, yes, a class having two polymorphic member variables. None of that yucky stuff about remembering not to leak the first one when the second fails to clone... just two normal member variables. I'd like to see this in boost:: and then std::. Because unique_ptr is so well digested by now, it feels right that this could be done relatively quickly. The only nit I had in the paper was that after all the banging on about it being a value type, we are given operator bool, operator* and operator->, making it pointer-like again. Could operator T& and operator T const& work? Pete
Peter Bartlett wrote:
The only nit I had in the paper was that after all the banging on about it being a value type, we are given operator bool, operator* and operator->, making it pointer-like again. Could operator T& and operator T const& work?
Polymorphic means virtual functions, and when you have a polymorphic_value<T> pv, where T has a virtual function `f`, you can call `pv->f()`. With a conversion to T&, you can't call `pv.f()`.
On 20/11/2017 12:41, Peter Dimov wrote:
Peter Bartlett wrote:
The only nit I had in the paper was that after all the banging on about it being a value type, we are given operator bool, operator* and operator->, making it pointer-like again. Could operator T& and operator T const& work?
Polymorphic means virtual functions, and when you have a polymorphic_value<T> pv, where T has a virtual function `f`, you can call `pv->f()`. With a conversion to T&, you can't call `pv.f()`.
You could pass it as a parameter to something that accepts a T& or T const& and then make polymorphic calls from that, or alternatively locally define a separate reference variable: Container<Base> c(new Derived); Base& r = c; r.f(); // calls Derived::f() But yes, this is significantly messier (and more potentially surprising to users) than using operator-> instead. Additionally since polymorphic_value can be empty, retaining some pointer-like syntax seems preferable as again this makes it less surprising to consumers. Although on a peripherally related note, this reminds me of a language gripe I have with operator->, in that it is not used to resolve ->* expressions. This means that code such as (p->*f)(x) has to be changed to (*p.*f)(x) if p is converted from a raw to a smart pointer, because (almost) nobody ever implements operator->* explicitly. (Although I tried it as an experiment and it seems relatively straightforward to do so in C++11, albeit at the cost of injecting std::function.)
AMDG On 11/19/2017 04:41 PM, Peter Dimov via Boost wrote:
Peter Bartlett wrote:
The only nit I had in the paper was that after all the banging on about it being a value type, we are given operator bool, operator* and operator->, making it pointer-like again. Could operator T& and operator T const& work?
Polymorphic means virtual functions, and when you have a polymorphic_value<T> pv, where T has a virtual function `f`, you can call `pv->f()`. With a conversion to T&, you can't call `pv.f()`.
Also, (ab)using operator* and operator-> like this isn't something new. optional is the same. In Christ, Steven Watanabe
On 20 Nov 2017, at 00:41, Peter Dimov via Boost
wrote: Peter Bartlett wrote:
The only nit I had in the paper was that after all the banging on about it being a value type, we are given operator bool, operator* and operator->, making it pointer-like again. Could operator T& and operator T const& work?
Polymorphic means virtual functions, and when you have a polymorphic_value<T> pv, where T has a virtual function `f`, you can call `pv->f()`. With a conversion to T&, you can't call `pv.f()`.
I had a careful think about this. It seems to me that what is at fault is not the interface, but the name. For the reason of the example below, it is helpful that the interface is consistent with unique_ptr, reference_wrapper, and shared_ptr. However, I think it is fair to say that the suffix _value is misleading as to intent. Example: struct FooConcept { void operator()() const; virtual ~FooConcept() = default; }; template class OwnershipHandle> struct basic_foo_handle { using implementation_pointer = OwnershipHandle<FooConcept>; void operator()() const { (*impl_)(); } implementation_pointer impl_; }; // a unique, non-copyable Foo using unique_foo = basic_foo_handlestd::unique_ptr(); // a shared-body Foo using shared_foo = basic_foo_handlestd::shared_ptr(); // observer_ptr would be a more consistent concept name (what happened to that?) using foo_reference = basic_foo_handlestd::reference_wrapper(); // deep_copy_ptr might have been a more appropriate name? using copyable_foo = basic_foo_handleboost::polymorphic_value();
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
On 19 Nov 2017, at 21:31, Robert Ramey via Boost
wrote: On 11/16/17 1:14 AM, Jonathan Coe via Boost wrote: I'd like to propose adding the class-template `polymorphic_value` to boost. `polymorphic_value` is designed to allow the compiler to correctly generate special member functions for classes with polymorphic components (It's `any` with an interface). `polymorphic_value` has been proposed for standardisation in P0201 and has advanced through the Library Evolution group in Albuquerque (Nov 5-10). https://wg21.link/p0201 A working draft of the proposal and implementation can be found at https://github.com/jbcoe/polymorphic_value I gave a presentation about polymorphic_value at C++::London here: https://skillsmatter.com/skillscasts/9539-a-polymorphic-value-type-for-c-plu... Matt Calabrese has kindly offered to be review manager. Kind regards, Jon
I looked over the github repo and the standards proposals. I also looked over the posts in this thread. I'm thinking the the enthusiasm is a little premature. Just some random observations which occurred to me as I looked this over.
Explanation ===========
From looking at the proposed implementation and one small sentence:
"A polymorphic_value<T> may hold a an object of a class publicly derived from T"
which suggests to me that certain operations such as assigment, copy, operators? etc. could be used with different instances created with different types all derived from type T. Sort of like a variant whose underlying types is that set of types derived from T. I don't know if I got this right - but reading the text and looking at the code, this is the impression I get.
That’s pretty much right. For polymorphic_value there’s no facility for discovering the type like one might do for variant.
If I got it wrong, there are only really two possibilities:
a) I'm stupid b) The explanation/motivation isn't rich enough.
Just for the sake of argument, let's suppose that b) is the correct one.
The motivating case seems to be usage as constituent of a composite object. But this seems to me totally unrelated to the interesting features of the "polymorphic value_type". I can't see why it's included or what it shows.
So I would like to see some examples of problems that this would solve and how it would solve them. I would also like to see summary reference including valid expressions and type requirements on the type T parameter.
Tests ===== Looks OK - but I'd have to invest more effort to be sure.
Source Code =========== OK - I'm nit picking here. I found the extensive usage of white space meant that I could only display about 20 lines of my code on my monitor. I would have found less blank lines and more {} added to other lines a big help in being able to read the code. I don't want for this to go on a tangent which ends up at the tabs/spaces cul-de-sac. So don't feel the need to respond to this.
Soooooooo - In my humble opinion, this submission needs more work before it could seriously considered for review as a boost library.
Robert Ramey
Thanks Robert, that’s really helpful. I definitely need to do some work on documentation with some more fleshed out usage examples. I’ll happily reformat source to make it boost-ish. Is there a clang-format file that people (or maybe just you) tend to use? Kind regards Jon
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
On 11/19/17 2:34 PM, Jonathan Coe via Boost wrote:
Source Code =========== OK - I'm nit picking here. I found the extensive usage of white space meant that I could only display about 20 lines of my code on my monitor. I would have found less blank lines and more {} added to other lines a big help in being able to read the code. I don't want for this to go on a tangent which ends up at the tabs/spaces cul-de-sac. So don't feel the need to respond to this.
Soooooooo - In my humble opinion, this submission needs more work before it could seriously considered for review as a boost library.
Robert Ramey
Thanks Robert,
that’s really helpful. I definitely need to do some work on documentation with some more fleshed out usage examples.
I’ll happily reformat source to make it boost-ish. Is there a clang-format file that people (or maybe just you) tend to use?
LOL - I'm not going to suggest anything specific as that well get off into the boost reality distortion field. These are people who will break up with their coder girlfriends over tabs vs spaces. The general point is that you have to "sell" the library. Bombast isn't necessary (though it seems to work for Vinnie). It has to slip in really easily. You look it over a little, get interested, and before you realize it, you've consumed it. FWIW - my presentation at CPPCon 2015 - How you can make a boost library summarizes my views on the subject. Bump the speed to save time. https://www.youtube.com/watch?v=ACeNgqBKL7E Also the boost library incubator may have some useful information. The main thing to remember is that getting something accepted by Boost is quite different than getting it accepted by the standards committee. a) The boost process discourages stuff that no one is using b) the boost process discourages stuff for which the use case isn't obvious. c) The boost process is much, much faster than the committee process. d) Both are seriously frustrating e) Both are tedious - more work involved than one would think. But the committee process is even more dry and tedious.
Kind regards
Jon
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
From looking at the proposed implementation and one small sentence
I think it becomes a little clearer if you read the linked PR's motivation.
In a nutshell, it deduces and carries forward a type-erased copier, which
means you don't have to fiddle around with implementing a cloning strategy
on T or anything derived from it.
On 19 November 2017 at 22:31, Robert Ramey via Boost
On 11/16/17 1:14 AM, Jonathan Coe via Boost wrote:
I'd like to propose adding the class-template `polymorphic_value` to boost.
`polymorphic_value` is designed to allow the compiler to correctly generate special member functions for classes with polymorphic components (It's `any` with an interface).
`polymorphic_value` has been proposed for standardisation in P0201 and has advanced through the Library Evolution group in Albuquerque (Nov 5-10). https://wg21.link/p0201
A working draft of the proposal and implementation can be found at https://github.com/jbcoe/polymorphic_value
I gave a presentation about polymorphic_value at C++::London here: https://skillsmatter.com/skillscasts/9539-a-polymorphic- value-type-for-c-plus-plus
Matt Calabrese has kindly offered to be review manager.
Kind regards,
Jon
I looked over the github repo and the standards proposals. I also looked over the posts in this thread. I'm thinking the the enthusiasm is a little premature. Just some random observations which occurred to me as I looked this over.
Explanation ===========
From looking at the proposed implementation and one small sentence:
"A polymorphic_value<T> may hold a an object of a class publicly derived from T"
which suggests to me that certain operations such as assigment, copy, operators? etc. could be used with different instances created with different types all derived from type T. Sort of like a variant whose underlying types is that set of types derived from T. I don't know if I got this right - but reading the text and looking at the code, this is the impression I get.
If I got it wrong, there are only really two possibilities:
a) I'm stupid b) The explanation/motivation isn't rich enough.
Just for the sake of argument, let's suppose that b) is the correct one.
The motivating case seems to be usage as constituent of a composite object. But this seems to me totally unrelated to the interesting features of the "polymorphic value_type". I can't see why it's included or what it shows.
So I would like to see some examples of problems that this would solve and how it would solve them. I would also like to see summary reference including valid expressions and type requirements on the type T parameter.
Tests ===== Looks OK - but I'd have to invest more effort to be sure.
Source Code =========== OK - I'm nit picking here. I found the extensive usage of white space meant that I could only display about 20 lines of my code on my monitor. I would have found less blank lines and more {} added to other lines a big help in being able to read the code. I don't want for this to go on a tangent which ends up at the tabs/spaces cul-de-sac. So don't feel the need to respond to this.
Soooooooo - In my humble opinion, this submission needs more work before it could seriously considered for review as a boost library.
Robert Ramey
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman /listinfo.cgi/boost
On 11/19/17 2:38 PM, Richard Hodges via Boost wrote:
From looking at the proposed implementation and one small sentence
I think it becomes a little clearer if you read the linked PR's motivation.
Hmmm - I'm pretty sure I read that. On the paper I read, the third section I read is: "Motivation: Composite objects". That's the end of it. I guess that's OK for a standards proposal, but I think that Boost users expect more complete motivation and justification. Examples are helpful here. If it's better explained, one is likely to get more people willing to review it - which is better all around. BTW - our custom is bottom posting here. Robert Ramey
Jonathan Coe wrote:
I'd like to propose adding the class-template `polymorphic_value` to boost.
`polymorphic_value` is designed to allow the compiler to correctly generate special member functions for classes with polymorphic components (It's `any` with an interface).
`polymorphic_value` has been proposed for standardisation in P0201 and has advanced through the Library Evolution group in Albuquerque (Nov 5-10). https://wg21.link/p0201
A working draft of the proposal and implementation can be found at https://github.com/jbcoe/polymorphic_value
I gave a presentation about polymorphic_value at C++::London here: https://skillsmatter.com/skillscasts/9539-a-polymorphic-value-type-for-c-plu...
Matt Calabrese has kindly offered to be review manager.
I endorse this submission provided that the repo submitted is organized according to Boost standards with documentation in doc/, headers in include/boost/, tests in test/. For examples of how a library directory layout looks like, you can use small Boost libraries such as f.ex. https://github.com/boostorg/assert (documentation in AsciiDoc) and https://github.com/boostorg/align (documentation in QuickBook.) I had a very similar thing (called ref<T> at the time), complete with the copier and the deleter, many years ago that I never got around to proposing. It seems to have been lost along with the Yahoo Boost group. PS. The code is fine. There's no need to reformat it.
Jonathan Coe wrote:
I'd like to propose adding the class-template `polymorphic_value` to boost.
`polymorphic_value` is designed to allow the compiler to correctly generate special member functions for classes with polymorphic components (It's `any` with an interface).
`polymorphic_value` has been proposed for standardisation in P0201 and has advanced through the Library Evolution group in Albuquerque (Nov 5-10). https://wg21.link/p0201
Has the name "polymorphic_value" been bike-shedded already? It's a good name in principle, but not good from a usability point of view; too long, too hard to type without errors in the absence of autocompletion. - poly_value? - any_value? - basic_any? Also, - poly seems to be popular, but it's probably too short.
On 20 Nov 2017, at 13:37, Peter Dimov via Boost
wrote: Jonathan Coe wrote:
I'd like to propose adding the class-template `polymorphic_value` to boost.
`polymorphic_value` is designed to allow the compiler to correctly generate special member functions for classes with polymorphic components (It's `any` with an interface).
`polymorphic_value` has been proposed for standardisation in P0201 and has advanced through the Library Evolution group in Albuquerque (Nov 5-10). https://wg21.link/p0201
Has the name "polymorphic_value" been bike-shedded already?
It's a good name in principle, but not good from a usability point of view; too long, too hard to type without errors in the absence of autocompletion.
- poly_value? - any_value? - basic_any?
Also,
- poly
seems to be popular, but it's probably too short.
The name has been bike-shedded. I agree it’s a little long but it conveys meaning pretty clearly to me.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
On 20 November 2017 at 16:09, Jonathan Coe via Boost
On 20 Nov 2017, at 13:37, Peter Dimov via Boost
wrote: Jonathan Coe wrote:
I'd like to propose adding the class-template `polymorphic_value` to boost.
`polymorphic_value` is designed to allow the compiler to correctly generate special member functions for classes with polymorphic components (It's `any` with an interface).
`polymorphic_value` has been proposed for standardisation in P0201 and has advanced through the Library Evolution group in Albuquerque (Nov 5-10). https://wg21.link/p0201
Has the name "polymorphic_value" been bike-shedded already?
It's a good name in principle, but not good from a usability point of view; too long, too hard to type without errors in the absence of autocompletion.
- poly_value? - any_value? - basic_any?
Also,
- poly
seems to be popular, but it's probably too short.
The name has been bike-shedded. I agree it’s a little long but it conveys meaning pretty clearly to me.
As an opposing data-point I can offer my own experience. I was not previously aware of the PR so the name polymorphic_value came to my attention only yesterday. My initial reaction to the name was to think, "oh, it must be some kind of boost::any with some mechanism for providing operators - something I could use as a polymorphic key in a map" - you know, a kind of value. Clearly I was misled by the suffix _value. It took two readings of the PR to finally understand that this was actually a *pointer* with type-erased cloning. There was no clue to that in the name at all - at least to me. It seems to me that the previous name of cloned_ptr is a better choice. But then I seem to find myself at odds with the thinking of committee contributors more and more these days, so it's probably me. R
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/ mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/ mailman/listinfo.cgi/boost
Richard Hodges wrote:
It seems to me that the previous name of cloned_ptr is a better choice.
_value is fine IMO. You can have
vector
On 20 November 2017 at 15:43, Peter Dimov via Boost
Richard Hodges wrote:
It seems to me that the previous name of cloned_ptr is a better choice.
_value is fine IMO. You can have
vector
v; and then
v.push_back( Circle(10) ); v.push_back( Ellipse(10, 15) ); v.push_back( Square(11) );
I would drop the U* constructor though. It's a remnant of the times this was called a pointer. U&& is all that's needed.
It's unfortunate we have to use -> instead of . but that's what's available.
The pointer constructor is needed in migration paths from class heirarchies with a `Clone()` method. It also allows one to support objects coming from C_APIs. I'd avoid using it, but it does have its uses.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman /listinfo.cgi/boost
Jonathan Coe wrote:
The pointer constructor is needed in migration paths from class heirarchies with a `Clone()` method. It also allows one to support objects coming from C_APIs.
Supporting X* create(...); X* copy( X const* ); void destroy( X* ); is appropriate for a cloning pointer, but hasn't really much to do with polymorphic values. struct Shape { virtual ~Shape() = default; Shape* clone() const = 0; void draw() = 0; }; Shape* createCircle( int r ); is admittedly less clear-cut. Looking at my old code, what I did was supply both a cloning pointer (U*) and a polymorphic value (U&&) types, the latter a simple wrapper over the former.
On 20 Nov 2017, at 16:57, Peter Dimov via Boost
wrote: Jonathan Coe wrote:
The pointer constructor is needed in migration paths from class heirarchies with a `Clone()` method. It also allows one to support objects coming from C_APIs.
Supporting
X* create(...); X* copy( X const* ); void destroy( X* );
is appropriate for a cloning pointer, but hasn't really much to do with polymorphic values.
struct Shape { virtual ~Shape() = default; Shape* clone() const = 0; void draw() = 0; };
Shape* createCircle( int r );
is admittedly less clear-cut.
Looking at my old code, what I did was supply both a cloning pointer (U*) and a polymorphic value (U&&) types, the latter a simple wrapper over the former.
This was my original design too which was strongly opposed by LEWG.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Jonathan Coe wrote:
On 20 Nov 2017, at 16:57, Peter Dimov via Boost
wrote: Looking at my old code, what I did was supply both a cloning pointer (U*) and a polymorphic value (U&&) types, the latter a simple wrapper over the former.
This was my original design too which was strongly opposed by LEWG.
Looking at P0201R0, R1, R2, you only propose one class though. In R0, you
propose cloned_ptr, and in R1/R2, a value class. So you get value proponent
criticisms on R0 and pointer proponent criticisms on R2.
What I am suggesting is two classes.
template<class T> class cloning_ptr
{
public:
template
On 20 Nov 2017, at 17:59, Peter Dimov via Boost
wrote: Jonathan Coe wrote:
On 20 Nov 2017, at 16:57, Peter Dimov via Boost
> wrote: Looking at my old code, what I did was supply both a cloning pointer > (U*) and a polymorphic value (U&&) types, the latter a simple wrapper > over the former.
This was my original design too which was strongly opposed by LEWG.
Looking at P0201R0, R1, R2, you only propose one class though. In R0, you propose cloned_ptr, and in R1/R2, a value class. So you get value proponent criticisms on R0 and pointer proponent criticisms on R2.
What I am suggesting is two classes.
template<class T> class cloning_ptr { public:
template
explicit cloning_ptr( U*, C = C{}, D = D{} ); }; template<class T> class polymorphic_value { private:
cloning_ptr<T> p_;
public:
template
polymorphic_value(U&& u, C c = C{}, D d = D{} ): p_( c(forward<U>(u)), move(c), move(d) ) }; (+add T&& overload to default_copy.)
Two classes instead of one is not without its downsides, since they are very similar in both appearance in behavior, but on the plus side, this allows us to make the interface of the pointer class unapologetically pointer-like and the interface of the value class... well, as value-not-pointer-like as possible, which isn't much due to op->, but still. :-)
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
I’m proposing adding polymorphic_value to boost, not cloned_ptr. My submission to boost is intended to mirror my submission to the C++ standards committee. Regards Jon
On Mon, Nov 20, 2017 at 12:23 PM, Jonathan Coe via Boost < boost@lists.boost.org> wrote:
On 20 Nov 2017, at 17:59, Peter Dimov via Boost
wrote: Two classes instead of one is not without its downsides, since they are very similar in both appearance in behavior, but on the plus side, this allows us to make the interface of the pointer class unapologetically pointer-like and the interface of the value class... well, as value-not-pointer-like as possible, which isn't much due to op->, but still. :-)
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/ mailman/listinfo.cgi/boost
I’m proposing adding polymorphic_value to boost, not cloned_ptr. My submission to boost is intended to mirror my submission to the C++ standards committee.
To answer the proximate question, LEWG wanted nothing to do with clone_ptr, whether or not it is designed to support or interoperate with polymorphic_value. Jonathan, please correct me if I'm wrong. Zach
On 20 Nov 2017, at 18:29, Zach Laine via Boost
wrote: On Mon, Nov 20, 2017 at 12:23 PM, Jonathan Coe via Boost < boost@lists.boost.org> wrote:
On 20 Nov 2017, at 17:59, Peter Dimov via Boost
wrote: Two classes instead of one is not without its downsides, since they are very similar in both appearance in behavior, but on the plus side, this allows us to make the interface of the pointer class unapologetically pointer-like and the interface of the value class... well, as value-not-pointer-like as possible, which isn't much due to op->, but still. :-)
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/ mailman/listinfo.cgi/boost
I’m proposing adding polymorphic_value to boost, not cloned_ptr. My submission to boost is intended to mirror my submission to the C++ standards committee.
To answer the proximate question, LEWG wanted nothing to do with clone_ptr, whether or not it is designed to support or interoperate with polymorphic_value. Jonathan, please correct me if I'm wrong.
Zach
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Zac is correct. LEWG requested that const propagation was added to X and that it ceased to be pointer-like. I agree with their direction. Sean (Parent) gave a rather nice talk which mentioned this at code dive 2016: https://youtu.be/cK_kftBNgBc about 40 mins in.
Zach Laine wrote:
On Mon, Nov 20, 2017 at 12:23 PM, Jonathan Coe via Boost
wrote: I’m proposing adding polymorphic_value to boost, not cloned_ptr. My submission to boost is intended to mirror my submission to the C++ standards committee.
To answer the proximate question, LEWG wanted nothing to do with clone_ptr, whether or not it is designed to support or interoperate with polymorphic_value. Jonathan, please correct me if I'm wrong.
OK, but this makes the submission a bit different than ordinary. Usually, in the course of the Boost review process, reviewers suggest changes and improvements, and can base their acceptance vote on some of these changes being applied. If I understand correctly, polymorphic_value as proposed is not open to any changes, because it has already been blessed by the LWG. Done and dusted. So Jonathan does not actually solicit feedback. It is what it is, take it or leave it.
On Mon, Nov 20, 2017 at 1:32 PM, Peter Dimov via Boost < boost@lists.boost.org> wrote:
Zach Laine wrote:
On Mon, Nov 20, 2017 at 12:23 PM, Jonathan Coe via Boost < boost@lists.boost.org> wrote:
I’m proposing adding polymorphic_value to boost, not cloned_ptr. My > submission to boost is intended to mirror my submission to the C++ > standards committee.
To answer the proximate question, LEWG wanted nothing to do with clone_ptr, whether or not it is designed to support or interoperate with polymorphic_value. Jonathan, please correct me if I'm wrong.
OK, but this makes the submission a bit different than ordinary.
True enough. This exact scenario is unique AFAIK.
Usually, in the course of the Boost review process, reviewers suggest changes and improvements, and can base their acceptance vote on some of these changes being applied.
If I understand correctly, polymorphic_value as proposed is not open to any changes, because it has already been blessed by the LWG. Done and dusted.
That's not my understanding, nor what I expect. I'm one of the people who keeps insisting in LEWG that things go through Boost (or other avenues of widespread use) before being standardized. My expectation is that the review will be very instructive, even if the library is rejected. Rejection is actually a very important data point! I would expect LEWG to delay standardization or to do a substantial re-think of whether this should be standardized at all if it is rejected. So Jonathan does not actually solicit feedback. It is what it is, take it
or leave it.
I think that overstates it a bit, having talked to Jonathan about this. Again, Jonathan can correct me if I'm wrong. Zach
On 11/20/17 11:41 AM, Zach Laine via Boost wrote:
On Mon, Nov 20, 2017 at 1:32 PM, Peter Dimov via Boost <
... I'm one of the people who keeps insisting in LEWG that things go through Boost (or other avenues of widespread use) before being standardized.
+1 My expectation is that the
review will be very instructive, even if the library is rejected. Rejection is actually a very important data point! I would expect LEWG to delay standardization or to do a substantial re-think of whether this should be standardized at all if it is rejected.
So Jonathan does not actually solicit feedback. It is what it is, take it
or leave it.
I think that overstates it a bit, having talked to Jonathan about this. Again, Jonathan can correct me if I'm wrong.
FWIW - I think that boost should approach this as it always has. That is, either reject, accept or accept with some modest conditions. And I think the committee should do what IT usually does: accept, reject, or redesign leveraging on experience as provided by users and vendors. Boost and the Committee are related, but they are not the same. If they were, one would be superfluous. Robert Ramey
On 20 November 2017 at 20:01, Robert Ramey via Boost
On 11/20/17 11:41 AM, Zach Laine via Boost wrote:
On Mon, Nov 20, 2017 at 1:32 PM, Peter Dimov via Boost <
... I'm one of the people who
keeps insisting in LEWG that things go through Boost (or other avenues of widespread use) before being standardized.
+1
My expectation is that the
review will be very instructive, even if the library is rejected. Rejection is actually a very important data point! I would expect LEWG to delay standardization or to do a substantial re-think of whether this should be standardized at all if it is rejected.
So Jonathan does not actually solicit feedback. It is what it is, take it
or leave it.
I think that overstates it a bit, having talked to Jonathan about this. Again, Jonathan can correct me if I'm wrong.
FWIW - I think that boost should approach this as it always has. That is, either reject, accept or accept with some modest conditions.
And I think the committee should do what IT usually does: accept, reject, or redesign leveraging on experience as provided by users and vendors.
Boost and the Committee are related, but they are not the same. If they were, one would be superfluous.
Robert Ramey
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman /listinfo.cgi/boost
That's exactly what I'm hoping for. I don't want polymorphic_value to be given any form of special consideration. When I said "I’m proposing adding polymorphic_value to boost, not cloned_ptr. My submission to boost is intended to mirror my submission to the C++ standards committee." I did not mean that I do not want feedback, but that cloned_ptr is not part of my proposed boost library submission. LWG may yet reject polymorphic_value and I would hope that their decision will have little bearing on the boost review process. I include Sean's explanation of why cloned_ptr is 'broken' and why polymorphic_value is not: "The primary semantics of a “pointer” or “handle” type is that it is an object that refers to another object. Copying a pointer does not copy the underlying object, two pointers are equal if they refer to the same object. The relationship between copying and equality also extends to the semantics of const. A const pointer is distinct from a pointer to a const object. If we have a const object and make a copy of it, any operation on the const object should not modify the copy. Copying a polymorphic_value, copies the remote part. If we were to implement equality of a polymorphic value it would be by virtualizing a call to operator==() on the remote part. A const polymorphic_value also implies the remote part is const. These are value, not pointer, semantics. The requirement of using operator*() and operator-> for an object with value semantics is an unfortunate (but not unprecedented) hack. Unfortunately, we cannot overload operator.() so overloading the dereference operators are the best we can do. The same is true of std::optional, which also has value semantics. polymorphic_value, IMO, creates a nice balance between full type erasure (using something like Facebook’s (Eric Niebler’s) Folly/Poly library) and traditional inheritance with specified interfaces. It is also useful in non-polymphric settings (which is why I somewhat prefer the name “indirect_value”) where one wants to make the tradeoff to gain an efficient move operation and the expense of a heap allocation. polymorphic_value should not be called a “pointer” because it does not have pointer semantics anymore than std::optional or std::vector are pointers." I look forward to improving this already useful library utility with the help of the boost community.
I watched Sean Parent's talk covering what has now become polymorphic_value.
One thing that I am concerned about is Sean's insistence on propagating
const implicitly.
This would be at odds with the behaviour shared_ptr, unique_ptr, and
reference_wrapper.
Sometimes I want a const pointer to a mutable thing, and sometimes I want a
mutable pointer to a const thing (and sometimes I want to be able to
observe a thing without affecting its lifetime).
So my 2-pence would be that propagate_const should not be implicit in this
class.
My rationale is that an obvious use case for me would be manufacturing
specialisations on pointer_type allowing a consistent interface leading to
an inner implementation while simply changing ownership behaviour.
In that sense I am strongly of the view that the return type of
polymorphic_value<Foo>::operator*() const should be Foo& and not const Foo&.
If I want a polymorphic cloning pointer to const Foo I can declare it with
polymorphic_value<const Foo>.
I have never had reason to quibble with Sean's thinking before now, but on
this he is dead wrong.
If I want const propagation, it's simple enough to wrap any pointer in
propagate_const<>
This feels to me like idealists overriding pragmatists.
Or have I missed something obvious?
R
On 20 November 2017 at 20:41, Zach Laine via Boost
On Mon, Nov 20, 2017 at 1:32 PM, Peter Dimov via Boost < boost@lists.boost.org> wrote:
Zach Laine wrote:
On Mon, Nov 20, 2017 at 12:23 PM, Jonathan Coe via Boost < boost@lists.boost.org> wrote:
I’m proposing adding polymorphic_value to boost, not cloned_ptr. My > submission to boost is intended to mirror my submission to the C++ > standards committee.
To answer the proximate question, LEWG wanted nothing to do with clone_ptr, whether or not it is designed to support or interoperate with polymorphic_value. Jonathan, please correct me if I'm wrong.
OK, but this makes the submission a bit different than ordinary.
True enough. This exact scenario is unique AFAIK.
Usually, in the course of the Boost review process, reviewers suggest changes and improvements, and can base their acceptance vote on some of these changes being applied.
If I understand correctly, polymorphic_value as proposed is not open to any changes, because it has already been blessed by the LWG. Done and dusted.
That's not my understanding, nor what I expect. I'm one of the people who keeps insisting in LEWG that things go through Boost (or other avenues of widespread use) before being standardized. My expectation is that the review will be very instructive, even if the library is rejected. Rejection is actually a very important data point! I would expect LEWG to delay standardization or to do a substantial re-think of whether this should be standardized at all if it is rejected.
So Jonathan does not actually solicit feedback. It is what it is, take it
or leave it.
I think that overstates it a bit, having talked to Jonathan about this. Again, Jonathan can correct me if I'm wrong.
Zach
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/ mailman/listinfo.cgi/boost
AMDG On 11/20/2017 01:11 PM, Richard Hodges via Boost wrote:
I watched Sean Parent's talk covering what has now become polymorphic_value.
One thing that I am concerned about is Sean's insistence on propagating const implicitly.
This would be at odds with the behaviour shared_ptr, unique_ptr, and reference_wrapper.
None of these make copies. polymorphic_value is not called XXX_ptr precisely because its semantics are different from a pointer.
Sometimes I want a const pointer to a mutable thing, and sometimes I want a mutable pointer to a const thing (and sometimes I want to be able to observe a thing without affecting its lifetime).
This situation doesn't make sense for polymorphic_value.
So my 2-pence would be that propagate_const should not be implicit in this class.
My rationale is that an obvious use case for me would be manufacturing specialisations on pointer_type allowing a consistent interface leading to an inner implementation while simply changing ownership behaviour.
In that sense I am strongly of the view that the return type of polymorphic_value<Foo>::operator*() const should be Foo& and not const Foo&.
If I want a polymorphic cloning pointer to const Foo I can declare it with polymorphic_value<const Foo>.
I have never had reason to quibble with Sean's thinking before now, but on this he is dead wrong.
If I want const propagation, it's simple enough to wrap any pointer in propagate_const<>
This feels to me like idealists overriding pragmatists.
Or have I missed something obvious?
In Christ, Steven Watanabe
None of these make copies. polymorphic_value is not called XXX_ptr precisely because its semantics are different from a pointer.
shared_ptr, unique_ptr and reference_wrapper are all "different" from a pointer, but they all share 4 common traits: 1. The all manage/observe lifetime of another _single_ object in some defined but distinct way. 2. They all allow access to that object through operator* 3. They don't propagate const. 4. they don't have any pointery arithmetic behaviour Looking at the design history of polymorphic_value it seems that it originally came from a desire to complete the circle by providing another XXX_ptr which supported copying. This aim is _eminently useful_ as is evidenced by the numerous implementations of things like it on github (and in my own code). I also have an interest is such an object as standard because I always seem to end up needing one. I do not have a use case for a const-propagating one. Never have. I can specify const in the angle-brackets. I've done that probably once.
This situation doesn't make sense for polymorphic_value.
To you perhaps. However I have 3 projects on the go right now which could use polymorphic_value immediately as a retro-fit for home-made solutions *if it did not propagate const*. The concept of propagating const I can deal with trivially. To incorporate it into this class mixes concerns to the detriment of its usefulness (to me). So If it came to a vote and my voice had any weight, I would say: * with implicit const-propagation - NO * remove the const propagation - absolute YES additionally, ideally rename it back to cloned_ptr, (or indirect if you must). Because what it is absolutely not is a value. It is logically the same as the other 4 non-pointers listed above, it's just that it have different owned-object lifetime behaviour. I completely understand the value-centric argument. I am a strong proponent of it. My argument is that this is (or ought to be) a tool for *building* value types. It is not in of itself a value type, and neither can it ever be. It does not exhibit any "value" behaviour (equality and the like). R On 20 November 2017 at 21:35, Steven Watanabe via Boost < boost@lists.boost.org> wrote:
AMDG
I watched Sean Parent's talk covering what has now become
On 11/20/2017 01:11 PM, Richard Hodges via Boost wrote: polymorphic_value.
One thing that I am concerned about is Sean's insistence on propagating const implicitly.
This would be at odds with the behaviour shared_ptr, unique_ptr, and reference_wrapper.
None of these make copies. polymorphic_value is not called XXX_ptr precisely because its semantics are different from a pointer.
Sometimes I want a const pointer to a mutable thing, and sometimes I want a mutable pointer to a const thing (and sometimes I want to be able to observe a thing without affecting its lifetime).
This situation doesn't make sense for polymorphic_value.
So my 2-pence would be that propagate_const should not be implicit in this class.
My rationale is that an obvious use case for me would be manufacturing specialisations on pointer_type allowing a consistent interface leading to an inner implementation while simply changing ownership behaviour.
In that sense I am strongly of the view that the return type of polymorphic_value<Foo>::operator*() const should be Foo& and not const Foo&.
If I want a polymorphic cloning pointer to const Foo I can declare it with polymorphic_value<const Foo>.
I have never had reason to quibble with Sean's thinking before now, but on this he is dead wrong.
If I want const propagation, it's simple enough to wrap any pointer in propagate_const<>
This feels to me like idealists overriding pragmatists.
Or have I missed something obvious?
In Christ, Steven Watanabe
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/ mailman/listinfo.cgi/boost
On 20 Nov 2017, at 21:12, Richard Hodges via Boost
None of these make copies. polymorphic_value is not called XXX_ptr precisely because its semantics are different from a pointer.
shared_ptr, unique_ptr and reference_wrapper are all "different" from a pointer, but they all share 4 common traits:
1. The all manage/observe lifetime of another _single_ object in some defined but distinct way.
2. They all allow access to that object through operator*
3. They don't propagate const.
4. they don't have any pointery arithmetic behaviour
Looking at the design history of polymorphic_value it seems that it originally came from a desire to complete the circle by providing another XXX_ptr which supported copying.
This aim is _eminently useful_ as is evidenced by the numerous implementations of things like it on github (and in my own code).
I also have an interest is such an object as standard because I always seem to end up needing one.
I do not have a use case for a const-propagating one. Never have. I can specify const in the angle-brackets. I've done that probably once.
This situation doesn't make sense for polymorphic_value.
To you perhaps. However I have 3 projects on the go right now which could use polymorphic_value immediately as a retro-fit for home-made solutions *if it did not propagate const*.
The concept of propagating const I can deal with trivially. To incorporate it into this class mixes concerns to the detriment of its usefulness (to me).
So If it came to a vote and my voice had any weight, I would say:
* with implicit const-propagation - NO
* remove the const propagation - absolute YES
additionally, ideally rename it back to cloned_ptr, (or indirect if you must). Because what it is absolutely not is a value.
It is logically the same as the other 4 non-pointers listed above, it's just that it have different owned-object lifetime behaviour.
I completely understand the value-centric argument. I am a strong proponent of it.
My argument is that this is (or ought to be) a tool for *building* value types. It is not in of itself a value type, and neither can it ever be. It does not exhibit any "value" behaviour (equality and the like).
R
On 20 November 2017 at 21:35, Steven Watanabe via Boost < boost@lists.boost.org> wrote:
AMDG
On 11/20/2017 01:11 PM, Richard Hodges via Boost wrote: I watched Sean Parent's talk covering what has now become polymorphic_value.
One thing that I am concerned about is Sean's insistence on propagating const implicitly.
This would be at odds with the behaviour shared_ptr, unique_ptr, and reference_wrapper.
None of these make copies. polymorphic_value is not called XXX_ptr precisely because its semantics are different from a pointer.
Sometimes I want a const pointer to a mutable thing, and sometimes I want a mutable pointer to a const thing (and sometimes I want to be able to observe a thing without affecting its lifetime).
This situation doesn't make sense for polymorphic_value.
So my 2-pence would be that propagate_const should not be implicit in this class.
My rationale is that an obvious use case for me would be manufacturing specialisations on pointer_type allowing a consistent interface leading to an inner implementation while simply changing ownership behaviour.
In that sense I am strongly of the view that the return type of polymorphic_value<Foo>::operator*() const should be Foo& and not const Foo&.
If I want a polymorphic cloning pointer to const Foo I can declare it with polymorphic_value<const Foo>.
I have never had reason to quibble with Sean's thinking before now, but on this he is dead wrong.
If I want const propagation, it's simple enough to wrap any pointer in propagate_const<>
This feels to me like idealists overriding pragmatists.
Or have I missed something obvious?
In Christ, Steven Watanabe
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/ mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
It’s interesting how quickly people become polarised on this. One thing to note is that polymorphic_value<const T> is not the same as a const-propagating polymorphic_value<T>; I hope that puts us all on the same page. polymorphic_value is designed so that compiler-generated special member functions for objects with polymorphic components (sub-objects) are generated correctly. As such it needs to propagate const. There’s no sense in part of an object being mutable in a context where the object itself is immutable. polymorphic_value solves a very real problem and allows deletion of a large amount of error-prone boiler-plate code. Some people don’t want const-propagation because they favour a composable deep-copy + deep-const combination type. Some people have a use case for a deep-copying non const-propagating pointer-like hybrid type. Without the second category, the first is just an implementation detail. I’d really like to see real examples (not thought-experiments) that are solved by a type like cloned_ptr. I have never encountered one but my experience is not so broad and I’m well aware that absence of evidence is not evidence of absence.
sent direct to Jonathan in error - reproduced here:
polymorphic_value solves a very real problem and allows deletion of a large amount of error-prone boiler-plate code.
completely agree. It would allow deletion of even more code if it didn't propagate_const.
Without the second category, the first is just an implementation detail.
Fine. Let's make it a policy. Then everyone's happy. The truth will out.
I’d really like to see real examples
Sometimes (in a comms-based system, often) even though the handle object's
interface is const, and accessor will do some internal work which may need
to mutate the implementation (even on another thread). I spend a lot of
time writing comms/protocol code which I normally implement as asio
services. Database access, websockets, AMQP messaging, http, etc.
If you've spent any time with asio you'll know all about the handle-body
idiom and all the nasty boilerplate required to correctly implement
move/copy/sharing of io objects bound to an executor.
Sometimes I'll want the concept of an object and I may decide to give it
shared-body semantics. But then I realise I can get a
performance/correctness win by providing the same interface but with
different copy/move behaviour.
Sometimes I realise I need such an object which will just clone itself when
copied.
It is useful to write these objects in terms of:
template class Pointer>
struct basic_foo
{
// ..
Pointer
On 20 Nov 2017, at 21:12, Richard Hodges via Boost
wrote: None of these make copies. polymorphic_value is not called XXX_ptr precisely because its semantics are different from a pointer.
shared_ptr, unique_ptr and reference_wrapper are all "different" from a pointer, but they all share 4 common traits:
1. The all manage/observe lifetime of another _single_ object in some defined but distinct way.
2. They all allow access to that object through operator*
3. They don't propagate const.
4. they don't have any pointery arithmetic behaviour
Looking at the design history of polymorphic_value it seems that it originally came from a desire to complete the circle by providing another XXX_ptr which supported copying.
This aim is _eminently useful_ as is evidenced by the numerous implementations of things like it on github (and in my own code).
I also have an interest is such an object as standard because I always seem to end up needing one.
I do not have a use case for a const-propagating one. Never have. I can specify const in the angle-brackets. I've done that probably once.
This situation doesn't make sense for polymorphic_value.
To you perhaps. However I have 3 projects on the go right now which could use polymorphic_value immediately as a retro-fit for home-made solutions *if it did not propagate const*.
The concept of propagating const I can deal with trivially. To incorporate it into this class mixes concerns to the detriment of its usefulness (to me).
So If it came to a vote and my voice had any weight, I would say:
* with implicit const-propagation - NO
* remove the const propagation - absolute YES
additionally, ideally rename it back to cloned_ptr, (or indirect if you must). Because what it is absolutely not is a value.
It is logically the same as the other 4 non-pointers listed above, it's just that it have different owned-object lifetime behaviour.
I completely understand the value-centric argument. I am a strong proponent of it.
My argument is that this is (or ought to be) a tool for *building* value types. It is not in of itself a value type, and neither can it ever be. It does not exhibit any "value" behaviour (equality and the like).
R
On 20 November 2017 at 21:35, Steven Watanabe via Boost < boost@lists.boost.org> wrote:
AMDG
On 11/20/2017 01:11 PM, Richard Hodges via Boost wrote: I watched Sean Parent's talk covering what has now become polymorphic_value.
One thing that I am concerned about is Sean's insistence on propagating const implicitly.
This would be at odds with the behaviour shared_ptr, unique_ptr, and reference_wrapper.
None of these make copies. polymorphic_value is not called XXX_ptr precisely because its semantics are different from a pointer.
Sometimes I want a const pointer to a mutable thing, and sometimes I want a mutable pointer to a const thing (and sometimes I want to be able to observe a thing without affecting its lifetime).
This situation doesn't make sense for polymorphic_value.
So my 2-pence would be that propagate_const should not be implicit in this class.
My rationale is that an obvious use case for me would be manufacturing specialisations on pointer_type allowing a consistent interface leading to an inner implementation while simply changing ownership behaviour.
In that sense I am strongly of the view that the return type of polymorphic_value<Foo>::operator*() const should be Foo& and not const Foo&.
If I want a polymorphic cloning pointer to const Foo I can declare it with polymorphic_value<const Foo>.
I have never had reason to quibble with Sean's thinking before now, but on this he is dead wrong.
If I want const propagation, it's simple enough to wrap any pointer in propagate_const<>
This feels to me like idealists overriding pragmatists.
Or have I missed something obvious?
In Christ, Steven Watanabe
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/ mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/ mailman/listinfo.cgi/boost
It’s interesting how quickly people become polarised on this. One thing to note is that polymorphic_value<const T> is not the same as a const-propagating polymorphic_value<T>; I hope that puts us all on the same page.
polymorphic_value is designed so that compiler-generated special member functions for objects with polymorphic components (sub-objects) are generated correctly. As such it needs to propagate const. There’s no sense in part of an object being mutable in a context where the object itself is immutable.
polymorphic_value solves a very real problem and allows deletion of a large amount of error-prone boiler-plate code.
Some people don’t want const-propagation because they favour a composable deep-copy + deep-const combination type. Some people have a use case for a deep-copying non const-propagating pointer-like hybrid type. Without the second category, the first is just an implementation detail. I’d really like to see real examples (not thought-experiments) that are solved by a type like cloned_ptr. I have never encountered one but my experience is not so broad and I’m well aware that absence of evidence is not evidence of absence.
On 20 Nov 2017, at 22:11, Richard Hodges via Boost
wrote: sent direct to Jonathan in error - reproduced here:
polymorphic_value solves a very real problem and allows deletion of a large amount of error-prone boiler-plate code.
completely agree. It would allow deletion of even more code if it didn't propagate_const.
Without the second category, the first is just an implementation detail.
Fine. Let's make it a policy. Then everyone's happy. The truth will out.
I’d really like to see real examples
Sometimes (in a comms-based system, often) even though the handle object's interface is const, and accessor will do some internal work which may need to mutate the implementation (even on another thread). I spend a lot of time writing comms/protocol code which I normally implement as asio services. Database access, websockets, AMQP messaging, http, etc.
If you've spent any time with asio you'll know all about the handle-body idiom and all the nasty boilerplate required to correctly implement move/copy/sharing of io objects bound to an executor.
Sometimes I'll want the concept of an object and I may decide to give it shared-body semantics. But then I realise I can get a performance/correctness win by providing the same interface but with different copy/move behaviour.
Sometimes I realise I need such an object which will just clone itself when copied.
It is useful to write these objects in terms of:
template class Pointer> struct basic_foo { // ..
Pointer
impl_; }; now I can specialise:
struct unique_foo : basic_foostd:unique_ptr { }; struct shared_foo : basic_foostd:shared_ptr { }; struct value_foo : basic_fooboost::polymorphic_value { }; struct foo_observer : basic_foostd::reference_wrapper { };
I have implemented both the interface and the implementation only once and am now afforded complete flexibility in how I manage my foos.
With a tiny bit more templatery I can even automatically get:
auto a = unique_foo(...); auto b = shared_foo(std::move(a));
or
auto a = value_foo(...); auto b = a; auto c = shared_foo(std::move(a));
and I can always get:
auto o1 = foo_observer(b), o2 = foo_observer(c);
The consistency is important (at least to me) because it affords perfect composability.
On 20 November 2017 at 22:36, Jonathan Coe
wrote: On 20 Nov 2017, at 21:12, Richard Hodges via Boost
wrote: None of these make copies. polymorphic_value is not called XXX_ptr precisely because its semantics are different from a pointer.
shared_ptr, unique_ptr and reference_wrapper are all "different" from a pointer, but they all share 4 common traits:
1. The all manage/observe lifetime of another _single_ object in some defined but distinct way.
2. They all allow access to that object through operator*
3. They don't propagate const.
4. they don't have any pointery arithmetic behaviour
Looking at the design history of polymorphic_value it seems that it originally came from a desire to complete the circle by providing another XXX_ptr which supported copying.
This aim is _eminently useful_ as is evidenced by the numerous implementations of things like it on github (and in my own code).
I also have an interest is such an object as standard because I always seem to end up needing one.
I do not have a use case for a const-propagating one. Never have. I can specify const in the angle-brackets. I've done that probably once.
This situation doesn't make sense for polymorphic_value.
To you perhaps. However I have 3 projects on the go right now which could use polymorphic_value immediately as a retro-fit for home-made solutions *if it did not propagate const*.
The concept of propagating const I can deal with trivially. To incorporate it into this class mixes concerns to the detriment of its usefulness (to me).
So If it came to a vote and my voice had any weight, I would say:
* with implicit const-propagation - NO
* remove the const propagation - absolute YES
additionally, ideally rename it back to cloned_ptr, (or indirect if you must). Because what it is absolutely not is a value.
It is logically the same as the other 4 non-pointers listed above, it's just that it have different owned-object lifetime behaviour.
I completely understand the value-centric argument. I am a strong proponent of it.
My argument is that this is (or ought to be) a tool for *building* value types. It is not in of itself a value type, and neither can it ever be. It does not exhibit any "value" behaviour (equality and the like).
R
On 20 November 2017 at 21:35, Steven Watanabe via Boost < boost@lists.boost.org> wrote:
AMDG
On 11/20/2017 01:11 PM, Richard Hodges via Boost wrote: I watched Sean Parent's talk covering what has now become polymorphic_value.
One thing that I am concerned about is Sean's insistence on propagating const implicitly.
This would be at odds with the behaviour shared_ptr, unique_ptr, and reference_wrapper.
None of these make copies. polymorphic_value is not called XXX_ptr precisely because its semantics are different from a pointer.
Sometimes I want a const pointer to a mutable thing, and sometimes I want a mutable pointer to a const thing (and sometimes I want to be able to observe a thing without affecting its lifetime).
This situation doesn't make sense for polymorphic_value.
So my 2-pence would be that propagate_const should not be implicit in this class.
My rationale is that an obvious use case for me would be manufacturing specialisations on pointer_type allowing a consistent interface leading to an inner implementation while simply changing ownership behaviour.
In that sense I am strongly of the view that the return type of polymorphic_value<Foo>::operator*() const should be Foo& and not const Foo&.
If I want a polymorphic cloning pointer to const Foo I can declare it with polymorphic_value<const Foo>.
I have never had reason to quibble with Sean's thinking before now, but on this he is dead wrong.
If I want const propagation, it's simple enough to wrap any pointer in propagate_const<>
This feels to me like idealists overriding pragmatists.
Or have I missed something obvious?
In Christ, Steven Watanabe
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/ mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/ mailman/listinfo.cgi/boost
It’s interesting how quickly people become polarised on this. One thing to note is that polymorphic_value<const T> is not the same as a const-propagating polymorphic_value<T>; I hope that puts us all on the same page.
polymorphic_value is designed so that compiler-generated special member functions for objects with polymorphic components (sub-objects) are generated correctly. As such it needs to propagate const. There’s no sense in part of an object being mutable in a context where the object itself is immutable.
polymorphic_value solves a very real problem and allows deletion of a large amount of error-prone boiler-plate code.
Some people don’t want const-propagation because they favour a composable deep-copy + deep-const combination type. Some people have a use case for a deep-copying non const-propagating pointer-like hybrid type. Without the second category, the first is just an implementation detail. I’d really like to see real examples (not thought-experiments) that are solved by a type like cloned_ptr. I have never encountered one but my experience is not so broad and I’m well aware that absence of evidence is not evidence of absence.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
I have no experience with ASIO, thanks for taking the time to put some examples together. It will take me some time to digest and come back with questions. Pleasingly we seem to be debating how useful this type can be rather than whether it’s useful at all. Regards, Jon
It will take me some time to digest and come back with questions.
This is a subject close to my heart, so please feel free to question as much as you wish.
Pleasingly we seem to be debating how useful this type can be rather than whether it’s useful at all.
As far as I am concerned, cloned_ptr was the missing piece to the puzzle of
consistent handling of handle/body objects - particularly when polymorphic.
It allowed value-semantic coding to be a reality in a consistent way. Have
no fears over utility.
While pointers provide the power behind c++, I am strongly of the view that
building user code around value types is preferable from the points of view
of maintainability, elegance and provable correctness. With a little tweak
this class could spell the end for pointer-based paranoia in user code
forever. That's a wonderful thing.
What strikes me as the masterstroke in the proposed implementation is the
type-erased copy/deletion which eliminates the need for clone. I wish I'd
thought of it. In that respect your implementation is beautiful.
On 20 November 2017 at 23:37, Jonathan
On 20 Nov 2017, at 22:11, Richard Hodges via Boost < boost@lists.boost.org> wrote:
sent direct to Jonathan in error - reproduced here:
polymorphic_value solves a very real problem and allows deletion of a large amount of error-prone boiler-plate code.
completely agree. It would allow deletion of even more code if it didn't propagate_const.
Without the second category, the first is just an implementation detail.
Fine. Let's make it a policy. Then everyone's happy. The truth will out.
I’d really like to see real examples
Sometimes (in a comms-based system, often) even though the handle object's interface is const, and accessor will do some internal work which may need to mutate the implementation (even on another thread). I spend a lot of time writing comms/protocol code which I normally implement as asio services. Database access, websockets, AMQP messaging, http, etc.
If you've spent any time with asio you'll know all about the handle-body idiom and all the nasty boilerplate required to correctly implement move/copy/sharing of io objects bound to an executor.
Sometimes I'll want the concept of an object and I may decide to give it shared-body semantics. But then I realise I can get a performance/correctness win by providing the same interface but with different copy/move behaviour.
Sometimes I realise I need such an object which will just clone itself when copied.
It is useful to write these objects in terms of:
template class Pointer> struct basic_foo { // ..
Pointer
impl_; }; now I can specialise:
struct unique_foo : basic_foostd:unique_ptr { }; struct shared_foo : basic_foostd:shared_ptr { }; struct value_foo : basic_fooboost::polymorphic_value { }; struct foo_observer : basic_foostd::reference_wrapper { };
I have implemented both the interface and the implementation only once and am now afforded complete flexibility in how I manage my foos.
With a tiny bit more templatery I can even automatically get:
auto a = unique_foo(...); auto b = shared_foo(std::move(a));
or
auto a = value_foo(...); auto b = a; auto c = shared_foo(std::move(a));
and I can always get:
auto o1 = foo_observer(b), o2 = foo_observer(c);
The consistency is important (at least to me) because it affords perfect composability.
On 20 November 2017 at 22:36, Jonathan Coe
wrote: On 20 Nov 2017, at 21:12, Richard Hodges via Boost < boost@lists.boost.org> wrote:
None of these make copies. polymorphic_value is not called XXX_ptr precisely because its semantics are different from a pointer.
shared_ptr, unique_ptr and reference_wrapper are all "different" from a pointer, but they all share 4 common traits:
1. The all manage/observe lifetime of another _single_ object in some defined but distinct way.
2. They all allow access to that object through operator*
3. They don't propagate const.
4. they don't have any pointery arithmetic behaviour
Looking at the design history of polymorphic_value it seems that it originally came from a desire to complete the circle by providing another XXX_ptr which supported copying.
This aim is _eminently useful_ as is evidenced by the numerous implementations of things like it on github (and in my own code).
I also have an interest is such an object as standard because I always seem to end up needing one.
I do not have a use case for a const-propagating one. Never have. I can specify const in the angle-brackets. I've done that probably once.
This situation doesn't make sense for polymorphic_value.
To you perhaps. However I have 3 projects on the go right now which could use polymorphic_value immediately as a retro-fit for home-made solutions *if it did not propagate const*.
The concept of propagating const I can deal with trivially. To incorporate it into this class mixes concerns to the detriment of its usefulness (to me).
So If it came to a vote and my voice had any weight, I would say:
* with implicit const-propagation - NO
* remove the const propagation - absolute YES
additionally, ideally rename it back to cloned_ptr, (or indirect if you must). Because what it is absolutely not is a value.
It is logically the same as the other 4 non-pointers listed above, it's just that it have different owned-object lifetime behaviour.
I completely understand the value-centric argument. I am a strong proponent of it.
My argument is that this is (or ought to be) a tool for *building* value types. It is not in of itself a value type, and neither can it ever be. It does not exhibit any "value" behaviour (equality and the like).
R
On 20 November 2017 at 21:35, Steven Watanabe via Boost < boost@lists.boost.org> wrote:
AMDG
On 11/20/2017 01:11 PM, Richard Hodges via Boost wrote: I watched Sean Parent's talk covering what has now become polymorphic_value.
One thing that I am concerned about is Sean's insistence on propagating const implicitly.
This would be at odds with the behaviour shared_ptr, unique_ptr, and reference_wrapper.
None of these make copies. polymorphic_value is not called XXX_ptr precisely because its semantics are different from a pointer.
Sometimes I want a const pointer to a mutable thing, and sometimes I want a mutable pointer to a const thing (and sometimes I want to be able to observe a thing without affecting its lifetime).
This situation doesn't make sense for polymorphic_value.
So my 2-pence would be that propagate_const should not be implicit in this class.
My rationale is that an obvious use case for me would be manufacturing specialisations on pointer_type allowing a consistent interface leading to an inner implementation while simply changing ownership behaviour.
In that sense I am strongly of the view that the return type of polymorphic_value<Foo>::operator*() const should be Foo& and not const Foo&.
If I want a polymorphic cloning pointer to const Foo I can declare it with polymorphic_value<const Foo>.
I have never had reason to quibble with Sean's thinking before now, but on this he is dead wrong.
If I want const propagation, it's simple enough to wrap any pointer in propagate_const<>
This feels to me like idealists overriding pragmatists.
Or have I missed something obvious?
In Christ, Steven Watanabe
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/ mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/ mailman/listinfo.cgi/boost
It’s interesting how quickly people become polarised on this. One thing to note is that polymorphic_value<const T> is not the same as a const-propagating polymorphic_value<T>; I hope that puts us all on the same page.
polymorphic_value is designed so that compiler-generated special member functions for objects with polymorphic components (sub-objects) are generated correctly. As such it needs to propagate const. There’s no sense in part of an object being mutable in a context where the object itself is immutable.
polymorphic_value solves a very real problem and allows deletion of a large amount of error-prone boiler-plate code.
Some people don’t want const-propagation because they favour a composable deep-copy + deep-const combination type. Some people have a use case for a deep-copying non const-propagating pointer-like hybrid type. Without the second category, the first is just an implementation detail. I’d really like to see real examples (not thought-experiments) that are solved by a type like cloned_ptr. I have never encountered one but my experience is not so broad and I’m well aware that absence of evidence is not evidence of absence.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/ mailman/listinfo.cgi/boost
I have no experience with ASIO, thanks for taking the time to put some examples together. It will take me some time to digest and come back with questions. Pleasingly we seem to be debating how useful this type can be rather than whether it’s useful at all.
Regards,
Jon
On 20 November 2017 at 22:51, Richard Hodges
It will take me some time to digest and come back with questions.
This is a subject close to my heart, so please feel free to question as much as you wish.
Pleasingly we seem to be debating how useful this type can be rather than whether it’s useful at all.
As far as I am concerned, cloned_ptr was the missing piece to the puzzle of consistent handling of handle/body objects - particularly when polymorphic. It allowed value-semantic coding to be a reality in a consistent way. Have no fears over utility.
While pointers provide the power behind c++, I am strongly of the view that building user code around value types is preferable from the points of view of maintainability, elegance and provable correctness. With a little tweak this class could spell the end for pointer-based paranoia in user code forever. That's a wonderful thing.
What strikes me as the masterstroke in the proposed implementation is the type-erased copy/deletion which eliminates the need for clone. I wish I'd thought of it. In that respect your implementation is beautiful.
On 20 November 2017 at 23:37, Jonathan
wrote: On 20 Nov 2017, at 22:11, Richard Hodges via Boost < boost@lists.boost.org> wrote:
sent direct to Jonathan in error - reproduced here:
polymorphic_value solves a very real problem and allows deletion of a large amount of error-prone boiler-plate code.
completely agree. It would allow deletion of even more code if it didn't propagate_const.
Without the second category, the first is just an implementation detail.
Fine. Let's make it a policy. Then everyone's happy. The truth will out.
I’d really like to see real examples
Sometimes (in a comms-based system, often) even though the handle object's interface is const, and accessor will do some internal work which may need to mutate the implementation (even on another thread). I spend a lot of time writing comms/protocol code which I normally implement as asio services. Database access, websockets, AMQP messaging, http, etc.
If you've spent any time with asio you'll know all about the handle-body idiom and all the nasty boilerplate required to correctly implement move/copy/sharing of io objects bound to an executor.
Sometimes I'll want the concept of an object and I may decide to give it shared-body semantics. But then I realise I can get a performance/correctness win by providing the same interface but with different copy/move behaviour.
Sometimes I realise I need such an object which will just clone itself when copied.
It is useful to write these objects in terms of:
template class Pointer> struct basic_foo { // ..
Pointer
impl_; }; now I can specialise:
struct unique_foo : basic_foostd:unique_ptr { }; struct shared_foo : basic_foostd:shared_ptr { }; struct value_foo : basic_fooboost::polymorphic_value { }; struct foo_observer : basic_foostd::reference_wrapper { };
I have implemented both the interface and the implementation only once and am now afforded complete flexibility in how I manage my foos.
With a tiny bit more templatery I can even automatically get:
auto a = unique_foo(...); auto b = shared_foo(std::move(a));
or
auto a = value_foo(...); auto b = a; auto c = shared_foo(std::move(a));
and I can always get:
auto o1 = foo_observer(b), o2 = foo_observer(c);
The consistency is important (at least to me) because it affords perfect composability.
On 20 November 2017 at 22:36, Jonathan Coe
wrote: On 20 Nov 2017, at 21:12, Richard Hodges via Boost < boost@lists.boost.org> wrote:
None of these make copies. polymorphic_value is not called XXX_ptr precisely because its semantics are different from a pointer.
shared_ptr, unique_ptr and reference_wrapper are all "different" from a pointer, but they all share 4 common traits:
1. The all manage/observe lifetime of another _single_ object in some defined but distinct way.
2. They all allow access to that object through operator*
3. They don't propagate const.
4. they don't have any pointery arithmetic behaviour
Looking at the design history of polymorphic_value it seems that it originally came from a desire to complete the circle by providing another XXX_ptr which supported copying.
This aim is _eminently useful_ as is evidenced by the numerous implementations of things like it on github (and in my own code).
I also have an interest is such an object as standard because I always seem to end up needing one.
I do not have a use case for a const-propagating one. Never have. I can specify const in the angle-brackets. I've done that probably once.
This situation doesn't make sense for polymorphic_value.
To you perhaps. However I have 3 projects on the go right now which could use polymorphic_value immediately as a retro-fit for home-made solutions *if it did not propagate const*.
The concept of propagating const I can deal with trivially. To incorporate it into this class mixes concerns to the detriment of its usefulness (to me).
So If it came to a vote and my voice had any weight, I would say:
* with implicit const-propagation - NO
* remove the const propagation - absolute YES
additionally, ideally rename it back to cloned_ptr, (or indirect if you must). Because what it is absolutely not is a value.
It is logically the same as the other 4 non-pointers listed above, it's just that it have different owned-object lifetime behaviour.
I completely understand the value-centric argument. I am a strong proponent of it.
My argument is that this is (or ought to be) a tool for *building* value types. It is not in of itself a value type, and neither can it ever be. It does not exhibit any "value" behaviour (equality and the like).
R
On 20 November 2017 at 21:35, Steven Watanabe via Boost < boost@lists.boost.org> wrote:
AMDG
> On 11/20/2017 01:11 PM, Richard Hodges via Boost wrote: > I watched Sean Parent's talk covering what has now become polymorphic_value. > > One thing that I am concerned about is Sean's insistence on propagating > const implicitly. > > This would be at odds with the behaviour shared_ptr, unique_ptr, and > reference_wrapper. >
None of these make copies. polymorphic_value is not called XXX_ptr precisely because its semantics are different from a pointer.
> Sometimes I want a const pointer to a mutable thing, and sometimes I want a > mutable pointer to a const thing (and sometimes I want to be able to > observe a thing without affecting its lifetime). >
This situation doesn't make sense for polymorphic_value.
> So my 2-pence would be that propagate_const should not be implicit in this > class. > > My rationale is that an obvious use case for me would be manufacturing > specialisations on pointer_type allowing a consistent interface leading to > an inner implementation while simply changing ownership behaviour. > > In that sense I am strongly of the view that the return type of > polymorphic_value<Foo>::operator*() const should be Foo& and not const Foo&. > > If I want a polymorphic cloning pointer to const Foo I can declare it with > polymorphic_value<const Foo>. > > I have never had reason to quibble with Sean's thinking before now, but on > this he is dead wrong. > > If I want const propagation, it's simple enough to wrap any pointer in > propagate_const<> > > This feels to me like idealists overriding pragmatists. > > Or have I missed something obvious? >
In Christ, Steven Watanabe
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/ mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/ mailman/listinfo.cgi/boost
It’s interesting how quickly people become polarised on this. One thing to note is that polymorphic_value<const T> is not the same as a const-propagating polymorphic_value<T>; I hope that puts us all on the same page.
polymorphic_value is designed so that compiler-generated special member functions for objects with polymorphic components (sub-objects) are generated correctly. As such it needs to propagate const. There’s no sense in part of an object being mutable in a context where the object itself is immutable.
polymorphic_value solves a very real problem and allows deletion of a large amount of error-prone boiler-plate code.
Some people don’t want const-propagation because they favour a composable deep-copy + deep-const combination type. Some people have a use case for a deep-copying non const-propagating pointer-like hybrid type. Without the second category, the first is just an implementation detail. I’d really like to see real examples (not thought-experiments) that are solved by a type like cloned_ptr. I have never encountered one but my experience is not so broad and I’m well aware that absence of evidence is not evidence of absence.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman /listinfo.cgi/boost
I have no experience with ASIO, thanks for taking the time to put some examples together. It will take me some time to digest and come back with questions. Pleasingly we seem to be debating how useful this type can be rather than whether it’s useful at all.
Regards,
Jon
Do you have sample code you might be able to share to illustrate this point: "Sometimes (in a comms-based system, often) even though the handle object's interface is const, and accessor will do some internal work which may need to mutate the implementation (even on another thread)." I'm afraid this example is sufficiently removed from my day-to-day experience that I struggle to see what you mean without code. An utterly unambiguous example that's not driven by a theoretical desire for type consistency will motivate adding `cloned_ptr`. `polymorphic_value` should probably stay as it is, I would add `cloned_ptr` too as they serve rather different purposes. regards, Jon PS There may be considerable to-and-fro in putting an example together, would it be wise to take this discussion off list?
On 21-11-17 09:45, Jonathan Coe via Boost wrote:
Do you have sample code you might be able to share to illustrate this point: "Sometimes (in a comms-based system, often) even though the handle object's interface is const, and accessor will do some internal work which may need to mutate the implementation (even on another thread)." I'm afraid this example is sufficiently removed from my day-to-day experience that I struggle to see what you mean without code.
I'm not sure, but I'm seeing `handle` as something completely different, unrelated to `polymorphic_value`. The implementation of a handle's body could benefit a lot from `polymorphic_value`, but - in my mind a `polymorphic_value` has - by definition - value semantics, and a such _requires_ const-propagation always (because that's consistent witht he core language value semantics). - likewise, the const-ness of a handle never propagates to it's body Different patterns, different semantics, different type, I think Cheers, Seth
On 21 Nov 2017, at 17:30, Seth via Boost
wrote: On 21-11-17 09:45, Jonathan Coe via Boost wrote: Do you have sample code you might be able to share to illustrate this point: "Sometimes (in a comms-based system, often) even though the handle object's interface is const, and accessor will do some internal work which may need to mutate the implementation (even on another thread)." I'm afraid this example is sufficiently removed from my day-to-day experience that I struggle to see what you mean without code.
I'm not sure, but I'm seeing `handle` as something completely different, unrelated to `polymorphic_value`.
The implementation of a handle's body could benefit a lot from `polymorphic_value`, but
- in my mind a `polymorphic_value` has - by definition - value semantics, and a such _requires_ const-propagation always (because that's consistent witht he core language value semantics).
- likewise, the const-ness of a handle never propagates to it's body
Different patterns, different semantics, different type, I think
Cheers,
Seth
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
I would agree that polymorphic_value and cloned_ptr solve different problems. My proposed addition to boost is polymorphic_value, I could possibly be convinced to propose cloned_ptr too. Regards Jon
I would agree that polymorphic_value and cloned_ptr solve different
Jonathan Coe wrote:
problems. My proposed addition to boost is polymorphic_value, I could
possibly be convinced to propose cloned_ptr too.
After making my bold claims of the wrongness of propagating const by
default yesterday (in the light of writing reactive I/O services), I have
taken some time to go back over old code and re-reason in terms of
polymorphic_value.
My concern was around scenarios where the outer handle on the main thread
wants to do something "constful" to the implementation, but this would
require non-const access to the impl by a resulting closure or handler
running in the IO thread.
Embarrassingly it turns out that under these circumstances the only time I
ever need mutable access are:
1. to mutate a mutex - which can of course be solved by making the mutex
mutable.
2. to modify a "use count" - in which case the solution is angling towards
a shared_ptr or intrusive_ptr implementation handle anyway.
So on balance, although on grounds of interface consistency it pains me to
say it, I am forced to agree that there is no harm in my use case in
propagating constness, and I certainly accept that propagating const makes
the writing of handle-body value-types less error prone, and in this
scenario is definitely a _good thing_.
In short, I am persuaded.
Thank you for your patience.
R
On 21 November 2017 at 20:08, Jonathan Coe via Boost
On 21 Nov 2017, at 17:30, Seth via Boost
wrote: On 21-11-17 09:45, Jonathan Coe via Boost wrote: Do you have sample code you might be able to share to illustrate this point: "Sometimes (in a comms-based system, often) even though the handle object's interface is const, and accessor will do some internal work which may need to mutate the implementation (even on another thread)." I'm afraid this example is sufficiently removed from my day-to-day experience that I struggle to see what you mean without code.
I'm not sure, but I'm seeing `handle` as something completely different, unrelated to `polymorphic_value`.
The implementation of a handle's body could benefit a lot from `polymorphic_value`, but
- in my mind a `polymorphic_value` has - by definition - value semantics, and a such _requires_ const-propagation always (because that's consistent witht he core language value semantics).
- likewise, the const-ness of a handle never propagates to it's body
Different patterns, different semantics, different type, I think
Cheers,
Seth
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/ mailman/listinfo.cgi/boost
I would agree that polymorphic_value and cloned_ptr solve different problems. My proposed addition to boost is polymorphic_value, I could possibly be convinced to propose cloned_ptr too.
Regards
Jon
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/ mailman/listinfo.cgi/boost
On 22 Nov 2017, at 07:40, Richard Hodges via Boost
wrote: Jonathan Coe wrote:
I would agree that polymorphic_value and cloned_ptr solve different problems. My proposed addition to boost is polymorphic_value, I could possibly be convinced to propose cloned_ptr too.
After making my bold claims of the wrongness of propagating const by default yesterday (in the light of writing reactive I/O services), I have taken some time to go back over old code and re-reason in terms of polymorphic_value.
My concern was around scenarios where the outer handle on the main thread wants to do something "constful" to the implementation, but this would require non-const access to the impl by a resulting closure or handler running in the IO thread.
Embarrassingly it turns out that under these circumstances the only time I ever need mutable access are:
1. to mutate a mutex - which can of course be solved by making the mutex mutable.
2. to modify a "use count" - in which case the solution is angling towards a shared_ptr or intrusive_ptr implementation handle anyway.
So on balance, although on grounds of interface consistency it pains me to say it, I am forced to agree that there is no harm in my use case in propagating constness, and I certainly accept that propagating const makes the writing of handle-body value-types less error prone, and in this scenario is definitely a _good thing_.
In short, I am persuaded.
Thank you for your patience.
R
On 21 November 2017 at 20:08, Jonathan Coe via Boost
wrote: On 21 Nov 2017, at 17:30, Seth via Boost
wrote: On 21-11-17 09:45, Jonathan Coe via Boost wrote: Do you have sample code you might be able to share to illustrate this point: "Sometimes (in a comms-based system, often) even though the handle object's interface is const, and accessor will do some internal work which may need to mutate the implementation (even on another thread)." I'm afraid this example is sufficiently removed from my day-to-day experience that I struggle to see what you mean without code.
I'm not sure, but I'm seeing `handle` as something completely different, unrelated to `polymorphic_value`.
The implementation of a handle's body could benefit a lot from `polymorphic_value`, but
- in my mind a `polymorphic_value` has - by definition - value semantics, and a such _requires_ const-propagation always (because that's consistent witht he core language value semantics).
- likewise, the const-ness of a handle never propagates to it's body
Different patterns, different semantics, different type, I think
Cheers,
Seth
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/ mailman/listinfo.cgi/boost
I would agree that polymorphic_value and cloned_ptr solve different problems. My proposed addition to boost is polymorphic_value, I could possibly be convinced to propose cloned_ptr too.
Regards
Jon
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/ mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Thanks for taking the time to write this. If any of your thought experiments graduated to full code snippets, I’d love to see them. I’m sure you won’t be the last person who would like to see justification for const-propagation Regards Jon
AMDG On 11/20/2017 02:12 PM, Richard Hodges via Boost wrote:
None of these make copies. polymorphic_value is not called XXX_ptr precisely because its semantics are different from a pointer.
shared_ptr, unique_ptr and reference_wrapper are all "different" from a pointer, but they all share 4 common traits:
1. The all manage/observe lifetime of another _single_ object in some defined but distinct way.
This is stated in an overly general way to artificially make it cover cloning_ptr. Copying objects is in no way an extension of deleting objects when they are no longer needed.
2. They all allow access to that object through operator*
3. They don't propagate const.
4. they don't have any pointery arithmetic behaviour
Looking at the design history of polymorphic_value it seems that it originally came from a desire to complete the circle by providing another XXX_ptr which supported copying.
You shouldn't think of it as a pointer. polymorphic_value is not a pointer that copies automatically. It's a value that allows runtime polymorphism.
This aim is _eminently useful_ as is evidenced by the numerous implementations of things like it on github (and in my own code).
I also have an interest is such an object as standard because I always seem to end up needing one.
I do not have a use case for a const-propagating one. Never have. I can specify const in the angle-brackets. I've done that probably once.
This situation doesn't make sense for polymorphic_value.
To you perhaps. However I have 3 projects on the go right now which could use polymorphic_value immediately as a retro-fit for home-made solutions *if it did not propagate const*.
The concept of propagating const I can deal with trivially. To incorporate it into this class mixes concerns to the detriment of its usefulness (to me).
So If it came to a vote and my voice had any weight, I would say:
* with implicit const-propagation - NO
* remove the const propagation - absolute YES
additionally, ideally rename it back to cloned_ptr, (or indirect if you must). Because what it is absolutely not is a value.
How is it not a value?
It is logically the same as the other 4 non-pointers listed above, it's just that it have different owned-object lifetime behaviour.
I completely understand the value-centric argument. I am a strong proponent of it.
My argument is that this is (or ought to be) a tool for *building* value types. It is not in of itself a value type, and neither can it ever be. It does not exhibit any "value" behaviour (equality and the like).
I don't understand what you mean. The most important feature of a "value" is that copies are disjoint, which is precisely what copying the stored object guarantees. In Christ, Steven Watanabe
On 20 Nov 2017, at 15:32, Peter Dimov via Boost
wrote: Jonathan Coe wrote:
The name has been bike-shedded. I agree it’s a little long but it conveys meaning pretty clearly to me.
Out of curiosity, do you use the library? Does not having to type the name annoy you?
I’ve been a long-term user of code completion tools like YouCompleteMe (or even basic textual completion in Vim) so doubt I can provide a very useful data point.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
participants (17)
-
Andrey Semashev
-
Beman Dawes
-
Gavin Lambert
-
Glen Fernandes
-
Jonathan
-
Jonathan Coe
-
Mathias Gaunard
-
Paul A. Bristow
-
Peter Bartlett
-
Peter Dimov
-
Richard Hodges
-
Robert Ramey
-
Seth
-
Steven Watanabe
-
Vicente J. Botet Escriba
-
Vinnie Falco
-
Zach Laine