[Top][All Lists]

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

Re: C++11 move semantics

From: Hans Åberg
Subject: Re: C++11 move semantics
Date: Sun, 4 Mar 2018 19:24:27 +0100

> On 4 Mar 2018, at 18:47, Frank Heckenbach <address@hidden> wrote:
> Hans Åberg wrote:
>>>> Later Bison versions work with unique_ptr; add %require to the
>>>> grammar to make sure one does not compile with older versions.
>>> Which version? I tried 3.0.4 (the latest I could find;
>> That version is OK. In the past, there was a C hack where the
>> default rule action was implemented by always doing $$ = $1, which
>> does not work with unique_ptr.
> I remember it used to do this before every action, even
> user-supplied actions, which was questionable.

OK in C, as it just copied the chunk.

> But now I see, it
> doesn't do it at all, even with no user action. This seems to
> contradict the documentation
> https://www.gnu.org/software/bison/manual/html_node/Actions.html
> : If you don't specify an action for a rule, Bison supplies a
> : default: $$ = $1
> Is this intentional? If so, I'd have to add this action to some of
> my rules (in some cases with std::move). Good to know this now.

The way it should work now is providing if no explicit action is give, 
otherwise not. Before, one always got it first, before the eventual explicit 

> But anyway, the issues with unique_ptr and other move-only types are
> not mainly in the actions, but more in the generated code, starting
> with the make_FOO functions. Again, I don't see that the default
> versions in 3.0.4 support moving. Do you use another version?

No versions support moving, and 3.0.4 may be the latest. The objects must be 
locations where it is expires, and that may not work well with the Bison parser.

>>> I'm not really convinced deque is the way to go. It adds some
>>> runtime overhead, maybe small, for what is really a single-ended
>>> queue, i.e. stack. So if copying can be avoided, as my patches seem
>>> to indicate, vector seems preferable.
>> Most time is typically spent in the lexer and the actions, so the
>> parser is usually not much to worry about: just write so it is
>> clear and easy to maintain.
> I don't think deque makes it any clearer; the code should be the
> same, provided stack_symbol_type has proper move semantics, which it
> needs anyway.

The problem is that it isn't developed currently.

> (In fact, after my patches, I could remove the
> assignment operator from lalr1.cc. It was specially provided for
> vector::push_back, but is no more needed then.)

The Bison distributed skeleton file might change, and then yours become does 
not benefit from that.

>>>> For the untyped grammar C++ parser (the typed does not work
>>>> properly),
>>> What is this? I'm still starting with C++ bison. I've been using the
>>> calc example which uses %skeleton "lalr1.cc", and that seems to be
>>> the only C++ skeleton I see, except for glr.cc (I don't need GLR
>>> yet).
>> There is a C++ equivalent of %union that allows for attaching
>> types to the grammar rules, but there seems to be an issue with
>> its variants (might be fixed using C++17 std::variant though).
>> I found a typed grammar of not much use in a highly dynamic language.
> That may be so, but both my implementation language (C++) and my
> target language are strongly typed, and so are all terminals and
> nonterminals in my grammar.

Then a typed grammar might be of use to you, but they reported problems with 
the C++ version.

> But again, what/where is this "untyped grammar C++ parser" you
> mentioned? I might try it, but I don't see it anywhere.

Just don't use %union.

> And when you say "the typed does not work properly", are you
> referring to lalr1.cc? What doesn't work? With the calc++ example
> I saw no problems, but it's just a toy, of course. So if there are
> serious problems, I'd like to know about them before I try to port
> my parser.

It was an issue with the variants.

>>> As I said, in most cases, I want to use unique_ptr or plain objects
>>> without pointers (if they're small).
>>> For those (few) other cases, I don't really want to introduce GC;
>>> I strongly prefer RAII. And that's especially true in those projects
>>> I use bison: the parser deals only with a small fraction of all the
>>> objects at runtime; most objects are used by other parts of the
>>> program, yet GC would impose itself on them globally. RAII
>>> (shared_ptr) deletes objects when necessary without going through
>>> the millions of other live objects, and lets me do proper cleanup
>>> via destructors.
>> Reference counts are tricky to use and get right, so avoid them in
>> general if you can;
> I don't think they're very tricky. shared_ptr does everything behind
> the scenes, except in special cases such as circular references.

If you have something not too complicated, they are might work fine.

> But of course, unique_ptr is always preferable when it does the job.

It might suffice for passing values around in the grammar actions.

>> if the use is limited to keeping track of the references in the
>> grammar, shared_ptr might be OK. A fellow on the Bison Help list
>> decided to go for unique_ptr.
> I think we agree here. If I'd always use shared_ptr, I wouldn't have
> any problems since it's copyable. But as I said, I want to use
> unique_ptr (or other move-only types) in most cases, that's why I
> need move semantics.

You might start with unique_ptr to see if it suffices. There is no Bison 
support for move semantics to be expected any time soon.

reply via email to

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