C++ Logo

liaison

Advanced search

Re: [wg14/wg21 liaison] type-generic lambdas

From: Uecker, Martin <Martin.Uecker_at_[hidden]>
Date: Sun, 11 Apr 2021 12:55:13 +0000

Hello Jens,

Am Sonntag, den 11.04.2021, 14:32 +0200 schrieb Jens Gustedt via Liaison:
...
> on Sun, 11 Apr 2021 11:15:22 +0000 you ("Uecker, Martin"
> <Martin.Uecker_at_med.uni-goettingen.de>) wrote:
>
> > My main concern with all this is less about some finite look ahead
> > but something else:
> >
> > In C is is possible to do type checking during parsing and directly
> > produce an intermediate code (or in theory even machine code).
> > There is no need to have an AST and some compiler do not have this.
> > Without goto we could go more or less directly to SSA.
> >
> > With type generic lambdas this is not possible anymore. You then
> > need to be able to parse arbitrary code without type information
> > and perform the type checking later when the lambda is specialized.
> >
> > [](auto x){ ... arbitrary c code with unknown types ... }
> >
> > What is an ICE may also depends on type and folding then also
> > needs to be delayed.
> >
> > At the moment only the preprocessor moves tokens around and
> > parsing, type checking, and ICE folding can be done in one pass
> > with limited look ahead.
> >
> > Note, that this is a superficious issue introduced by the lambda
> > syntax.
>
> No it isn't, this is only for tg lambdas with `auto` parameters, which
> even in C++ is a relatively new feature.

Yes, for tg lambdas. This is what I said at the beginning.

> > As the use case for type-generic lambdas is that they
> > are produced by a macro are instantiated directly, this could
> > be done differenty, i.e. the statement expressions of GCC do
> > not have this problem:
> >
> > #define foo(x) \
> > ({ \
> > auto y = (x); // type generic argument
> > ... arbitrary code using y ... \
> > })
> >
> > After expnading the macro the code can be parsed with full type
> > information because the argument is inserted by the preprocessor
> > at a position where it can be parsed frst.
>
> Your example is a bit misleading. The natural C++ replacement for your
> macro above is
>
> #define foo(x) \
> [&, y = (x)] mutable { /* type generic argument */ \
> ... arbitrary code using y ... \
> }()
>
> No `auto` parameters are need for such a thing. For the proposed C
> feature (without `mutable`) this would be
>
> #define foo(x) \
> [&, yy = (x)] { /* type generic argument */ \
> auto y = yy; \
> ... arbitrary code using y ... \
> }()
>
> This may not be pretty, but here also no `auto` parameters are needed
> and the full functionality is already there.

Ok, this is fine, but only further confirms that we create
a problem for parsers for no good reason.

> The only real and new purpose of type-generic macros with `auto`
> parameters is the second usage for them, namely the conversion into
> function pointers. A type-generic lambda macro
>
> #define mysin [](auto x){ \
> /* implement a tg formula for the sinus function */ \
> return val; \
> }
>
> double (*sin)(double) = mysin;
>
> is not so easily emulated by gcc's compound statement plus nested
> functions, if at all.

I agree and this is very nice. Here the parsing problem also does
not arise as the type of the pointer converted to is also already
known before the lambda is parsed.

> > In contrast, with type-generic lambdas:
> >
> > #define foo [](auto y){ \
> > ... arbitrary code using y ... \
> > }
> >
> > the code needs to be parsed without knowing the type of 'y'
> > and only then is the argument is parsed which yields this
> > information.
>
> If used in a call expression, yes, in a sense.

Yes. But with the syntax it must be possible to parse such
expressions. If we can outlaw this, i.e. calling tg lambda
directly, this would also solve the problem.

> But that problem can also be solved with lookahead for a ballanced
> token sequence, finding the arguments to the call (if this is a call),
> doing the type inference for the parameters, and then scanning the
> body of the lambda for real.
>
> So yes, this has a cost, but I think that this cost is limited.

It is certainly doable. The problem is that this requires unbounded
lookahead and also recursively if tg lambdas are nested.

One could implement this as another preprocessing step that shuffles
around the tokens before the parser even sees it.

But alls this seems like this would be a natural fit for the
preprocessor which suffles around tokens anyway.

> The big advantage is that this would bring us feature-complete
> type-generic math library (or similar) that enables us to provide
> function pointers where they are needed.

I agree about the advantages of the general concept. I just point
out the very unfortunate choice of syntax.

Best,
Martin


______________________________________________
> Liaison mailing list
> Liaison_at_[hidden]
> Subscription: https://lists.isocpp.org/mailman/listinfo.cgi/liaison
> Link to this post: http://lists.isocpp.org/liaison/2021/04/0395.php

Received on 2021-04-11 07:55:23