[llvm-dev] enable_shared_from_this fails at runtime when inherited privately
Christian Schneider via llvm-dev
llvm-dev at lists.llvm.org
Thu Aug 29 03:49:29 PDT 2019
Am 29.08.19 um 12:07 schrieb Jonathan Wakely:
> On Thu, 29 Aug 2019 at 10:15, Christian Schneider
> <cschneider at radiodata.biz> wrote:
>>
>> Hello,
>> I just discovered, that, when using enable_shared_from_this and
>> inheriting it privately, this fails at runtime.
>> I made a small example:
>>
>> #include <memory>
>> #include <boost/shared_ptr.hpp>
>> #include <boost/make_shared.hpp>
>> #include <boost/enable_shared_from_this.hpp>
>>
>> #ifndef prefix
>> #define prefix std
>> #endif
>>
>> class foo:
>> prefix::enable_shared_from_this<foo>
>> {
>> public:
>> prefix::shared_ptr<foo> get_sptr()
>> {
>> return shared_from_this();
>> }
>> };
>>
>> int main()
>> {
>> auto a = prefix::make_shared<foo>();
>> auto b = a->get_sptr();
>> return 0;
>> }
>>
>> This compiles fine, but throws a weak_ptr exception at runtime.
>> I'm aware, that the implementation requires, that
>> enable_shared_from_this needs to be publicly inherited, but as a first
>> time user, I had to find this out the hard way, as documentations (I
>> use, ie. cppreference.com) don't mention it, probably because it's not a
>> requirement of the standard.
>
> It definitely is a requirement of the standard. The new wording we
> added via http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0033r1.html#spec
> says that the base's weak_ptr is only initialized when the base class
> is "unambiguous and accessible". It doesn't say that an ambiguous or
> inaccessible base class makes the program ill-formed, so we're not
> allowed to reject such a program. >
I see. As far as I understand, this sentence was removed:
Requires: enable_shared_from_this<T> shall be an accessible base class
of T. *this shall be a subobject of an object t of type T. There shall
be at least one shared_ptr instance p that owns &t.
As far as I read it, this required enable_shared_from_this to be public
accessible. Do you know (or someone else), why it was removed?
I find it a little, umm..., inconvenient, that the compiler happily
accepts it when it is clear that it never ever can work...
>> On the other hand, if you compile the code with additional
>> -Dprefix=boost (and needed boost stuff installed, of course), it gives a
>> compiler error (
>> gcc: 'boost::enable_shared_from_this<foo>' is an inaccessible base of 'foo';
>> clang: error: cannot cast 'boost::shared_ptr<foo>::element_type' (aka
>> 'foo') to its private base class 'boost::enable_shared_from_this<foo>')
>
> That seems like a bug in Boost.
>
When Boost wants to follow the standard, then yes. If not i would see it
as a feature, see above :)
>> I'm think, it would be helpful, if the std implemntions also would fail
>> at compile time already, and wanted to ask if this would be
>> possible/feasible.
>
> No, that would not conform to the standard.
>
Clear.
More information about the llvm-dev
mailing list