From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 59106 invoked by alias); 29 Aug 2019 11:43:36 -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 59097 invoked by uid 89); 29 Aug 2019 11:43:36 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-1.8 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=ham version=3.3.1 spammy=cschneider@radiodata.biz, cschneiderradiodatabiz, H*f:CAH6eHdRo, H*f:sk:FX8DnS8 X-HELO: mail-wm1-f67.google.com Received: from mail-wm1-f67.google.com (HELO mail-wm1-f67.google.com) (209.85.128.67) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 29 Aug 2019 11:43:34 +0000 Received: by mail-wm1-f67.google.com with SMTP id t9so3489629wmi.5 for ; Thu, 29 Aug 2019 04:43:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=baNpdjlL/L5NEQA5qDe7GGiHW+i6sWq3yU57rIxLUJo=; b=T0MId2qfMXnDsKdl8dS4Rivj03MyMLHPICytx1the1K8aaNtrJnqjdamjk+IvGkdRX a69DUBw5UMXLD5485izyUmxyYQqZLA9Dn47RMyC+tFXUW6JL2B0gAaHnvFhmCsaRYjo1 6xpDwrczJPtVcIMLRqRf80eGp+WpDocom1KKdy42REAQbj+7Z90v7UFbTx31Xy/OED8p tOwOTGfy2eDE27v6n3bxE56M3QRDIW0N1vg4PWZoL5q1d5unmIGLNlc9E7Le9R0XC1kp 04/2neqmZgjA/tLoPyLr0w90STKaWfikXuJUc24aj+5AJ8LVri9qtt1VAKV0P3wy1dVi ddqQ== MIME-Version: 1.0 References: <271ebc76-2e27-d4b4-6cd6-9f7a5c8ff7a1@radiodata.biz> <0deb1007-1622-2487-8fe1-5f7557204f37@radiodata.biz> In-Reply-To: <0deb1007-1622-2487-8fe1-5f7557204f37@radiodata.biz> From: Jonathan Wakely Date: Thu, 29 Aug 2019 11:43:00 -0000 Message-ID: Subject: Re: enable_shared_from_this fails at runtime when inherited privately To: Christian Schneider Cc: llvm-dev@lists.llvm.org, "gcc@gcc.gnu.org" , christian@ch-sc.de, premmers@radiodata.biz Content-Type: text/plain; charset="UTF-8" X-IsSubscribed: yes X-SW-Source: 2019-08/txt/msg00226.txt.bz2 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. > 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++.