bison-patches
[Top][All Lists]
Advanced

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

Re: RFC: lalr1.cc: support move semantics


From: Frank Heckenbach
Subject: Re: RFC: lalr1.cc: support move semantics
Date: Tue, 11 Sep 2018 17:21:46 +0200

Hi Akim!

> >>    That's easy for inner types, when the parser's functions pass arguments 
> >> to
> >>    each other.  Funtions facing the user (make_NUMBER, make_STRING, etc.)
> >>    should support both rvalue-refs (for instance to support move-only 
> >> types:
> >>    make_INT (std::make_unique<int> (1))), and lvalue-refs (so that we can 
> >> pass
> >>    a variable: make_INT (my_int)).  To avoid the multiplication of the
> >>    signatures (there is also the location), let's take the argument by 
> >> copy.
> > 
> > By copy? Do you mean by value? (Maybe these terms were used
> > synonymously pre-C++11, but in the presence of move semantics I
> > think it's better to distinguish them clearly; same for the naming
> > of YY_COPY.)
> 
> I agree with using 'by value' (which is more traditional, but is
> less clear than 'by copy' precisely now that we have 'by move', which
> is rather called by rvalue-ref, indeed), but really YY_VALUE instead of
> YY_COPY looks confusing: it's not about a semantical value.  And
> it matches nicely with YY_MOVE_OR_COPY, imho.  But maybe I'm too
> cautious.

Maybe I misunderstood the context. I assumed you meant to write

  (1)
  foo (T bar);

instead of

  (2)
  foo (const T & bar);
  foo (T && bar);

In fact, (1) is good practice in modern C++ (except, of course, for
constructors which need to be written as (2); assignment operators
often are too, but don't strictly need to be).

If you call (1) "foo (std::move (baz));", baz will be moved to the
bar parameter, and foo might then move that to some internal field,
so no copy is ever involved, so I wouldn't call this "by copy", if
that's what you mean. (Of course, you can also call (1) foo by copy,
in which case a copy constructor will construct the T argument
before foo is actually called, so I consider this more of a
caller-side thing.)

So maybe I'm too cautious here, but especially in a context like
this, I'd read anything "copy" as, things are actually copied, which
is a no-no (with "big" types) or simply impossible (with move-only
types).

> >> +  template <typename... Args>
> >> +  ustring
> >> +  make_ustring (Args&&... args)
> >> +  {
> >> +    // std::make_unique is C++14.
> >> +    return std::unique_ptr<std::string>(new 
> >> std::string(std::forward<Args>(args)...));
> >> +  }
> > 
> > From that template it's not a far way to a full make_unique<T>
> > implementation you could define conditional on C++<14.
> 
> I'm running this example with -std=c++11, make_unique is not
> an option.

I meant you could implement make_unique (which would look mostly
like the above function, with another template type argument)
conditional on C++<14, and then use make_unique in the caller
unconditionally.

> This test actually requires '#define private public'
> to work...

Which might be UB:
https://stackoverflow.com/questions/27778908/define-private-to-public-in-c

> > I personally don't think "auto x = T (v);"
> > adds much compared to "T x = v;" anyway,
> 
> I'm addict to auto almost everywhere.  It's way more consistent.

I'm more like auto almost almost always. ;) I'm fine with
"auto b = false;", but when I have to spell out the type anyway, I
think the "auto" form just makes it longer for no benefit. But
that's just personal opinion.

> Likewise, I hate 'typedef' with a passion, so I'm very happy to
> use 'using' everywhere.  But not an option in lalr1.cc. :)

I only slightly prefer "using", and use it in new code, but haven't
found a compelling reason to convert "typedef" to "using" in my
existing code (though it actually should be quite easy to
semi-automate, and the code requires C++14 anyway).

Regards,
Frank



reply via email to

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