Saturday, October 14, 2017

Digest for comp.lang.c++@googlegroups.com - 8 updates in 3 topics

Nikki Locke <nikki@trumphurst.com>: Oct 14 10:23PM

Available C++ Libraries FAQ
 
URL: http://www.trumphurst.com/cpplibs/
 
This is a searchable list of libraries and utilities (both free
and commercial) available to C++ programmers.
 
If you know of a library which is not in the list, why not fill
in the form at http://www.trumphurst.com/cpplibs/cppsub.php
 
Maintainer: Nikki Locke - if you wish to contact me, please use the form on the website.
Paavo Helde <myfirstname@osa.pri.ee>: Oct 14 10:23AM +0300

On 14.10.2017 1:40, Alf P. Steinbach wrote:
>> used otherwise in the codebase).
 
> I think maybe better to provide a constructor that forwards arguments to
> make_shared.
 
You mean a static factory function? Yes I do that as well. But this does
not solve the issue that a new std::shared_ptr can be constructed
accidentally from 'this' or from a C++ reference to the object.
 
Such a construction would actually work for some kind of smartpointers,
but not for std::shared_ptr, and may create a lot of hidden bugs in the
codebase when replacing the old smartpointer by the standard
std::shared_ptr. Been there, done that...
 
Cheers
Paavo
"Öö Tiib" <ootiib@hot.ee>: Oct 14 06:27AM -0700

On Friday, 13 October 2017 23:37:40 UTC+3, Vir Campestris wrote:
> class "shared_from_this" that allows you to hand out shared pointers safely.
 
> The first time you assign a pointer from your object it sets up the
> shared_ptr, links the internal weak_ptr, and all is fine.
 
Yes you are correct. Note that it is unusual case since the programmers
usually create new shared_ptr with make_shared or allocate_shared or
provide also deleter as well.
 
When someone constructs shared_ptr from raw pointer (without
also providing deleter) then I feel that it strongly smells like
newbie and is potentially copy-paste from stackoverflow or other
newbie site. Can anyone bring sane counter-example?
 
> If some **** later calls std::shared_ptr(this) you get an entirely new
> shared pointer, with a different ref count.
 
Yes, when constructing a std::shared_ptr for an object that is
already managed by another std::shared_ptr then constructor is not
required to check for that (despite it is required to store weak
reference to enable_shared_from_this subobject) and so it will always
lead to undefined behavior.
 
> If the STL is smart enough to detect the first case why doesn't it give
> an error in the second?
 
> I know a codebase where it would have saved lots of problems :(
 
Because it is not required. The 'enable_shared_from_this' was limited
feature up to C++17 since there was even no way to check if the object
was managed by 'shared_ptr' at all or wasn't. Therefore usage of
'enable_shared_from_this' involved ensuring that *every* object
of that type was *always* already managed by 'shared_ptr'.
 
From C++17 we can finally make a check that (note how confusing
interface) when 'pT->weak_from_this().expired()' then the object
pointed at is not managed by 'shared_ptr<T>'. That still does
not make constructing shared_ptr from pT non-smelly or non-dangerous.
However it at least removes the curse that something derived from
'enable_shared_from_this' was not passable by value, usable as
automatic object, usable as element of container or usable as
member of class without rendering the whole 'enable_shared_from_this'
useless.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Oct 14 08:44PM +0200

On 10/14/2017 3:27 PM, Öö Tiib wrote:
 
> From C++17 we can finally make a check that (note how confusing
> interface) when 'pT->weak_from_this().expired()' then the object
> pointed at is not managed by 'shared_ptr<T>'.
 
I don't get what you mean here.
 
I'm not familiar with the `expired` function but one could always check
a weak pointer by trying to convert it to `shared_ptr`, and, checking in
cppreference, I see that `expired` was introduced in C++11 (maybe it was
there always in Boost, I don't know, but since the function is is
irrelevant its date of introduction doesn't matter).
 
As far as I know C++17 still lacks a way to check if a type T is derived
from some accessible and unique base class
`enabled_shared_from_this<U>`, doesn't it?
 
 
> automatic object, usable as element of container or usable as
> member of class without rendering the whole 'enable_shared_from_this'
> useless.
 
I don't get this either.
 
I think there is an issue with /moving/ an object of a type derived from
`enable_shared_from_this`.
 
But a weak pointer can be copied just fine, can't it?
 
 
Cheers!,
 
- Alf
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Oct 14 08:47PM +0200

On 10/14/2017 9:23 AM, Paavo Helde wrote:
 
> You mean a static factory function? Yes I do that as well. But this does
> not solve the issue that a new std::shared_ptr can be constructed
> accidentally from 'this' or from a C++ reference to the object.
 
Not entirely sure what you mean, but I didn't mean in-addition-to, I
meant instead-of.
 
Sort of like this:
 
 
namespace cppx {
using std::enable_if_t;
using std::enable_shared_from_this;
using std::forward;
using std::make_shared;
using std::shared_ptr;
 
template< class D, class B >
using Is_derived_and_base = std::is_base_of<B, D>;
 
template< class Referent >
class Shared_ptr
: public shared_ptr<Referent>
{
public:
template< class... Args >
Shared_ptr( Args&&... args )
: shared_ptr<Referent>( make_shared<Referent>(
forward<Args>( args )... ) )
{}
};
} // namespace cppx
 
 
 
Possibly also allow construction from a raw pointer to type derived from
`enable_shared_from_this`, and possibly also support construction from
raw pointer + deleter, but not just from any raw pointer.
 
 
 
> but not for std::shared_ptr, and may create a lot of hidden bugs in the
> codebase when replacing the old smartpointer by the standard
> std::shared_ptr.
 
Uhm?
 
 
Cheers!,
 
- Alf
"Öö Tiib" <ootiib@hot.ee>: Oct 14 12:35PM -0700

On Saturday, 14 October 2017 21:44:25 UTC+3, Alf P. Steinbach wrote:
> > interface) when 'pT->weak_from_this().expired()' then the object
> > pointed at is not managed by 'shared_ptr<T>'.
 
> I don't get what you mean here.
 
I will gladly try to explain then.
 
> cppreference, I see that `expired` was introduced in C++11 (maybe it was
> there always in Boost, I don't know, but since the function is is
> irrelevant its date of introduction doesn't matter).
 
The issue was not checking if 'weak_ptr' is pointing at valid object.
The issue was that 'enable_shared_from_this::weak_from_this()' was not
yet present in C++14 and so calling pT->weak_from_this() did not compile.
Calling pT->shared_from_this() however was undefined behavior on case
the object pointed at by pT was not managed by shared_ptr in C++14 (it
throws bad_weak_ptr in C++17).
 
> As far as I know C++17 still lacks a way to check if a type T is derived
> from some accessible and unique base class
> `enabled_shared_from_this<U>`, doesn't it?
 
May be that is not needed. On general case 'std::is_base_of' is plenty.
To avoid edge cases it is required from programmer that the
'enable_shared_from_this' base should be unique and accessible.
 
> > member of class without rendering the whole 'enable_shared_from_this'
> > useless.
 
> I don't get this either.
 
Here I am in dim what you don't get. I meant that now we can check if
object (derived publicly and uniquely from 'enable_shared_from_this')
is actually managed by shared_ptr. That significantly relaxes its
usage.
 
> I think there is an issue with /moving/ an object of a type derived from
> `enable_shared_from_this`.
 
Copying enable_shared_from_this does not copy the weak reference because
it does not make sense if to think about it a bit.
 
> But a weak pointer can be copied just fine, can't it?
 
Yes, copying weak_ptr increases weak count of managed object. With it
there are no issues.
Vir Campestris <vir.campestris@invalid.invalid>: Oct 14 09:24PM +0100

On 14/10/2017 14:27, Öö Tiib wrote:
> also providing deleter) then I feel that it strongly smells like
> newbie and is potentially copy-paste from stackoverflow or other
> newbie site. Can anyone bring sane counter-example?
 
Yes. If the constructor is private to force use of a factory function
make_shared won't compile. (I tried and failed to work out the correct
friend statement, then gave up)
 
Thanks everyone.
 
Andy
JiiPee <no@notvalid.com>: Oct 14 02:22PM +0100

vec contains many elements. This is not my real code, I only did it to
illustrate the problem. But I know already it was the unsigned issue. thanks
 
On 13/10/2017 18:36, Vlad from Moscow wrote:
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: