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.