On 25.02.2017 16:13, Ben Bacarisse wrote:
> "Alf P. Steinbach" <
alf.p.stein...@gmail.com> writes:
>
>> I'm not sure, but I think BCPL, which C was based on, supported
>> control structures within expressions; at least had curly braces in
>> expressions?
>
> It has expressions of the form VALOF <block> used like this:
>
> LET l = VALOF $(
> LET n, x = 0, 1
> WHILE x < y DO n, x = n+1, f(x)
> RESULTIS n
> $)
>
> In fact, that's how functions that need a block are defined.
>
Thanks! I was pretty sure it was supported, but I had some doubt
lingering. I never used the language.
[snip]
>>
>> struct Tracing
>> {
>> ~Tracing() { cout << "Tracing::<destroy>" << endl; }
>> Tracing() { cout << "Tracing::<init>" << endl; }
>> };
>>
>> $just
>> {
>> $let sum = $invoked{ int s{}; for( int i = 1; i <= 8; ++i ) s +=
>> i; return s; };
>
> I'm guessing this is the thunk being called and that it means:
>
> auto sum = [&]{
> int s{}; for( int i = 1; i <= 8; ++i ) s += i; return s;
> }();
>
>> cout << sum << endl;
>>
>> cout << endl;
>> $invoked_with( Tracing{} )
>> {
>> cout << "Hum!" << endl;
>> };
>> }
>>
>>
>> Here the % operator function is found via Argument Dependent Lookup
>> and invokes the specified lambda, producing an expression return value
>> via C++14 automatic return type deduction, and that works with MSVC
>> 2015. :)
>
> Where is the % operator being used? Is that masked by the $xyz stuff or
> is it in the header?
The `$defined` macro. I put the definition in a comment at top, but:
#define $invoked $e::impl::Gurkemeie{} % []()
Where `Gurkemeie` is an empty class defined in that namespace: its only
purpose is to guide Argument Dependent Lookup to find that `operator%`.
And now with your example to open my eyes, I see that this is just wrong
as a general definition. There should be a capture by reference. Thanks
again!
There is/will be a standard library invocation function in C++17,
¹`std::invoke`, and with C++11 the ²`std::reference_wrapper::operator()`
can invoke things. But these invokers put the invocation act, and any
arguments, textually after the lambda body. I feel that that's awkward,
that the most important information isn't up front, but later at the end.
Anyway, the starting point was `$invoked_with`, to define a way to add
RAII-like init and cleanup to a block of code, e.g. for automatic mutex
or a library envelope, without having to invent unnatural & unused names
for these objects. I implemented that first as a range based `for`, but
g++ complained with a warning about unused but assigned variable, even
when I made its constructor do things. Then I implemented it as a
conventional `for` loop, that iterated exactly once. But, during a visit
to a certain small room it occurred to me that if I did it with a lambda
with defaulted argument, then that same mechanism could be reused for
control structures in expressions, as with `$invoked`. I failed to see
that it would need a semicolon at the end, but I still think it's
better; just a single general mechanism.
Cheers!,
- Alf
Links:
¹ <url:
http://en.cppreference.com/w/cpp/utility/functional/invoke>
² <url:
http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper/operator()>