This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFA 02/22] Use RAII to save and restore scalars


On 09/30/2016 02:17 AM, Pedro Alves wrote:
> 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, 

Looks like it is -- Andrei Alexandrescu's ScopeGuard uses the
same trick:

  http://www.drdobbs.com/cpp/generic-change-the-way-you-write-excepti/184403758

Thanks,
Pedro Alves

> 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<typename T>
> 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<class T>
> scoped_restore_<T> make_scoped_restore (T *var)
> {
>   return scoped_restore_<T> (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: {<No data fields>}
> 
> To see the object's fields you'd have to downcast it manually, like:
> 
> (gdb) p (scoped_restore_<ui_out *>) scope
> $1 = {<scoped_restore_base> = {<No data fields>}, saved_var = 0x601050 <current_uiout>, saved_value = 0x0}
> 
> Not sure whether that's an issue.
> 
> Thanks,
> Pedro Alves
> 



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]