Christian Schneider via llvm-dev
2019-Aug-29 09:14 UTC
[llvm-dev] enable_shared_from_this fails at runtime when inherited privately
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.
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>')
I'm think, it would be helpful, if the std implemantions also would fail
at compile time already, and wanted to ask if this would be
possible/feasible.
BR, Christian
compilers:
gcc-Version 9.2.0 (Gentoo 9.2.0 p1)
clang version 8.0.1 (tags/RELEASE_801/final) (used with both
libstdc++.so.6 and libc++.so.1 (v8.0.1))
Jonathan Wakely via llvm-dev
2019-Aug-29 10:07 UTC
[llvm-dev] enable_shared_from_this fails at runtime when inherited privately
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.> 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.> I'm think, it would be helpful, if the std implemantions 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.
Christian Schneider via llvm-dev
2019-Aug-29 10:49 UTC
[llvm-dev] enable_shared_from_this fails at runtime when inherited privately
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.
Seemingly Similar Threads
- enable_shared_from_this fails at runtime when inherited privately
- [LLVMdev] Leaks in PBQPBuilderWithCoalescing::build ?
- [LLVMdev] Use of Smart Pointers in LLVM Projects
- [LLVMdev] Leaks in PBQPBuilderWithCoalescing::build ?
- IntrusiveRefCntPtr vs std::shared_ptr