From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 37993 invoked by alias); 30 Sep 2016 01:17:18 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 37899 invoked by uid 89); 30 Sep 2016 01:17:16 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-4.9 required=5.0 tests=BAYES_00,RP_MATCHES_RCVD,SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=salt X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 30 Sep 2016 01:17:15 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 559E03D94A; Fri, 30 Sep 2016 01:17:14 +0000 (UTC) Received: from [127.0.0.1] (ovpn01.gateway.prod.ext.ams2.redhat.com [10.39.146.11]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u8U1HBLC004422; Thu, 29 Sep 2016 21:17:12 -0400 Subject: Re: [RFA 02/22] Use RAII to save and restore scalars To: Trevor Saunders , Tom Tromey References: <1474949330-4307-1-git-send-email-tom@tromey.com> <1474949330-4307-3-git-send-email-tom@tromey.com> <20160927085937.com7c7ct4wuchzpg@ball> Cc: gdb-patches@sourceware.org From: Pedro Alves Message-ID: Date: Fri, 30 Sep 2016 01:40:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.2.0 MIME-Version: 1.0 In-Reply-To: <20160927085937.com7c7ct4wuchzpg@ball> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-SW-Source: 2016-09/txt/msg00420.txt.bz2 On 09/27/2016 09:59 AM, Trevor Saunders wrote: >> I had hoped that template parameter deduction would work here, but it >> did not, and so the patch uses explicit template parameters >> everywhere. > > yeah, you can't deduce template args from a constructor in C++ I don't know whether the trick below is usual, but you can work around that and end up with no-template-args-in-sight usage like this: void foo () { scoped_restore scope = make_scoped_restore (&some_global); ... } You'd do something like this: struct scoped_restore_base {}; template class scoped_restore_ : public scoped_restore_base { public: ... explicit scoped_restore (T *var) : saved_var (var), saved_value (*var) {} ~scoped_restore () { *saved_var = saved_value; } private: scoped_restore &operator= (const scoped_restore &rhs); // The saved variable. T *saved_var; // The saved value. T saved_value; }; typedef const scoped_restore_base &scoped_restore; template scoped_restore_ make_scoped_restore (T *var) { return scoped_restore_ (var); } The trick is making scoped_restore_ inherit a non-template class, and make "scoped_restore" a typedef for a const reference to the base class, since a const reference can bind to the temporary that is returned by make_scoped_restore, and it extends the temporary's lifetime. While copy elision / RVO makes it so that the temporary returned by value from make_scoped_restore is constructed directly in the caller instead of constructed and then copied out, you still have to provide the copy constructor, instead of "deleting" it as in your original patch. Copy elision was optional until C++17, but I believe all compilers worth their salt implement it. And if a compiler doesn't implement it, it's not a real issue, anyway, the code still works. The downside is that printing a scoped_restore object from gdb will just print the reference using the base type, so you won't see stored fields. (gdb) p scope $1 = (const scoped_restore) @0x7fffffffd910: {} To see the object's fields you'd have to downcast it manually, like: (gdb) p (scoped_restore_) scope $1 = { = {}, saved_var = 0x601050 , saved_value = 0x0} Not sure whether that's an issue. Thanks, Pedro Alves