From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 43788 invoked by alias); 29 Aug 2019 14:46:59 -0000 Mailing-List: contact gcc-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-owner@gcc.gnu.org Received: (qmail 43779 invoked by uid 89); 29 Aug 2019 14:46:59 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=2.6 required=5.0 tests=AWL,BAYES_00,BIZ_BODY,KAM_INFOUSMEBIZ,SPF_PASS autolearn=no version=3.3.1 spammy=H*F:D*biz, cschneider@radiodata.biz, cschneiderradiodatabiz, H*M:biz X-HELO: smtp.radiodata.biz Received: from smtp.radiodata.biz (HELO smtp.radiodata.biz) (116.203.112.52) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 29 Aug 2019 14:46:56 +0000 Received: from localhost (localhost [127.0.0.1]) by smtp.radiodata.biz (Postfix) with ESMTP id CA47B3E925; Thu, 29 Aug 2019 16:46:53 +0200 (CEST) Received: from smtp.radiodata.biz ([116.203.112.52]) by localhost (smtp.radiodata.biz [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id hBFpAXXMtpBE; Thu, 29 Aug 2019 16:46:46 +0200 (CEST) Received: from mail.radiodata.biz (p578044f8.dip0.t-ipconnect.de [87.128.68.248]) by smtp.radiodata.biz (Postfix) with ESMTPSA id 6EF9F3E924; Thu, 29 Aug 2019 16:46:46 +0200 (CEST) Received: from [192.168.2.143] (radiobox-gentoo.radiodata.xx [192.168.2.143]) by mail.radiodata.biz (Postfix) with ESMTPSA id 010C1202D2; Thu, 29 Aug 2019 16:46:45 +0200 (CEST) Subject: Re: enable_shared_from_this fails at runtime when inherited privately To: Jonathan Wakely Cc: llvm-dev@lists.llvm.org, "gcc@gcc.gnu.org" , christian@ch-sc.de, premmers@radiodata.biz References: <271ebc76-2e27-d4b4-6cd6-9f7a5c8ff7a1@radiodata.biz> <0deb1007-1622-2487-8fe1-5f7557204f37@radiodata.biz> From: Christian Schneider Message-ID: Date: Thu, 29 Aug 2019 14:46:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.8.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-SW-Source: 2019-08/txt/msg00229.txt.bz2 Am 29.08.19 um 13:44 schrieb Jonathan Wakely: > On Thu, 29 Aug 2019 at 12:43, Jonathan Wakely wrote: >> >> On Thu, 29 Aug 2019 at 11:50, Christian Schneider >> wrote: >>> >>> Am 29.08.19 um 12:07 schrieb Jonathan Wakely: >>>> On Thu, 29 Aug 2019 at 10:15, Christian Schneider >>>> 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 >>>>> #include >>>>> #include >>>>> #include >>>>> >>>>> #ifndef prefix >>>>> #define prefix std >>>>> #endif >>>>> >>>>> class foo: >>>>> prefix::enable_shared_from_this >>>>> { >>>>> public: >>>>> prefix::shared_ptr get_sptr() >>>>> { >>>>> return shared_from_this(); >>>>> } >>>>> }; >>>>> >>>>> int main() >>>>> { >>>>> auto a = prefix::make_shared(); >>>>> 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 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. >> >> No. It only required it to be publicly accessible if you called >> shared_from_this(). >> >>> Do you know (or someone else), why it was removed? >> >> Yes (look at the author of the paper :-). As I wrote in that paper: >> >> "The proposed wording removes the preconditions on shared_from_this so >> that it is now well-defined to call it on an object which is not owned >> by any shared_ptr, in which case shared_from_this would throw an >> exception." >> >> Previously it was undefined behaviour to call shared_from_this() if >> the base class hadn't been initialized to share ownership with a >> shared_ptr. That meant the following was undefined: >> >> #include >> struct X : std::enable_shared_from_this { }; >> int main() >> { >> X x; // not owned by a shared_ptr >> x.shared_from_this(); >> } >> >> Now this program is perfectly well-defined, but it throws an >> exception. There is no good reason to say that program has undefined >> behaviour (which means potentially unbounded types of errors) when we >> can just make it valid code that throws an exception when misused. > > And in order to make it well-defined, we tightened up the > specification to say exactly how and when the weak_ptr in a > enable_shared_from_this base class gets initialized. If it's not > possible to initialize it (e.g. because it's private) then it doesn't > initialize it. > OK, thx for clarification and insights. Since it is a requirement from the standard, I will add a note on cppreference.com, so that it is clear that it needs to be public inherited, and it silently fails if you don't inherit public. >> >>> I find it a little, umm..., inconvenient, that the compiler happily >>> accepts it when it is clear that it never ever can work... >> >> The code compiles and runs. It just doesn't do what you thought it >> would do. Welcome to C++.