[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: C++11 move semantics

From: Frank Heckenbach
Subject: Re: C++11 move semantics
Date: Fri, 09 Mar 2018 02:26:12 +0100

Hans Åberg wrote:

> > On 8 Mar 2018, at 00:33, Frank Heckenbach <address@hidden> wrote:
> > 
> >>> Sure, it's not required (nothing about the C++ mode is), but it
> >>> might be convenient for the user as it avoids a trap. I have a
> >>> number of such rules in my grammars, and if you hadn't mentioned it,
> >>> I'd have been caught by this, not even at compile-time, but at
> >>> runtime. (Though such a bug would probably be rather obvious and
> >>> easy to fix in all places, not the end of the world.)
> >> 
> >> It should complain if not having a not supported semicolon.
> > 
> > Not sure I follow you here. If I have a rule like "foo: bar;" where
> > foo and bar have the same (non-void) type, the C skeleton does
> > "$$ = $1"; the standard C++ skeleton just default-initializes $$
> > (so it will not be undefined, just empty). My patch does
> > "$$ = std::move ($1)" (effectively).
> We are speaking about different things here: In Yacc grammar one drop the ";".

OK, but how is this relevant here?

> > Since std::stack moves instead of copying when possible, not quite
> > so expensive. Also bison by default reserve()s 200 entries, and I
> > think you rarely need a parser stack deeper than this, so this might
> > be a theoretical problem.
> The type std::stack is older, but some benefits of std::deque are mentioned 
> here:
>   http://en.cppreference.com/w/cpp/container/deque

I think you rarely need a parser stack deeper than this, so I still
don't think that matters for Bison, or do you any such examples?

Anyway, while doing the C++11 changes in stack.hh, I now made it
possible to set other containers. If it makes you happy. :)

> >> Perhaps if it know that $1 expires, it can apply a move assignment.
> > 
> > It could do that if $1 is mentioned only once. In fact, I just
> > checked my grammars and in almost all cases that's so (not counting
> > a later "free ($1)" or "delete $1" which is part of the manual
> > pointer management which would disappear with unique_ptr); for me
> > that's because I prefer to keep my actions short and do all
> > non-trivial work in subfunctions.
> > 
> > It's still not a silver bullet: Others might prefer longer actions
> > that regularly mention $n more than once, and even I have at least
> > one such rule, basically:
> > 
> >  a: b c { $$ = $2.empty () ? $1 : combine ($1, $2); };
> > 
> > Here, moving from $1 would be safe in both places as only one is
> > executed; moving from $2 is safe in the combine() call, not in the
> > empty() call (but also not required, since empty() is a const member
> > function). That's not too difficult for a programmer to see, but
> > almost impossible for Bison to do automatically.
> > 
> > Of course, Bison could give up there (and possibly warn about it),
> > and still do automatic moving in other situations.
> I think it would be complicated, so just std::move for now.

I looked into the code. Just adding std::move seems rather easy, but
finding out if a $n is mentioned several times might be tricky on
the m4 level, might require changes to Bison itself.

And the question remains what to do then. One possibility would be
an option auto-move or such. If not set, std::move is not inserted;
if set it's always inserted, but Bison warns if $n is mentioned
several times.

Then there might need to be a way to suppress this warning for
individual cases which gets complicated again. Or there is no such
way, and if needed, one has to work around it. That would work fine
with my grammar -- for the few such rules as mentioned above I could
just move $n to temporaries. But for grammars that have this more
often, this might get cumbersome, so I'm not sure how useful such an
option would be to others.

Any ideas?

> > I did so at first, but then I realized that Bison would have to
> > replace "$$ =" with "return" which is dangerous as I said. So it
> > would probably be easier in the long run to leave this to the
> > programmer. (But again, I doubt this will be implemented.)
> And maybe the C++ standard does not admit one relying on it.

I think move on return (when the target is a local variable or
parameter) is guaranteed in recent standards (C++14 or so).

> >> [GC]
> >> 
> >> I use it for dynamic polymorphism like in Scheme/Guile, where you
> >> can't tell when the object expires.
> > 
> > shared_ptr also does it (and I used it where I need it), but ...
> The std::shared_ptr is simplistic,

I think you're one of few people to call it that. :) It has a number
of advanced features few people will ever use. The only thing I find
lacking is a way to release the object, and AIUI that's intentional
because of cross-thread optimization.

> > Lack of release method, so it would propagate throughout all my
> > code. See first mail in thread.
> I am not sure why you need it in the parser. Just put the object
> on the heap and use shared_ptr in the semantic value, but nowhere
> else.

That's exactly what I'd need a release method for when transferring
objects from the parsed structures to the rest of the program.

> You may do your own M4 files, and as Bison isn't development,
> there is no risk for it to become outdated, and maybe get it
> integrated later.

Seems so. I'm working on that now.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]