user643005
user643005

Reputation: 405

How to Emulate Statement Exprs GNU extension on Standard C++

I need to automatically translate from certain language to C++. The source language has the equivalent of Statement Exprs and I'm having a lot of difficulty replicating that on standard C++ (C++11, actually).

At first I considered lambdas, but the result is very ugly (with lambdas within lambdas within lambdas...) and possibly would bring the compiler to its knees when applied to large sources.

How could I replicate that GNU extension? It is imperative that semantics about construction/destruction/copying/etc are maintained, so translating this:

Foo foo( { ... declarations and statements ... } );

into this:

Foo foo;
... declarations and statements ...
foo = last result;

is not correct (as Foo is being constructed with default constructor and then assigned, instead of being constructed with the last value of the block of statements. Also, objects created inside the block of statements have a different lifetime on each case.)

Please note that this question also applies for the case where a program that uses that extension needs to be translated to Standard C++.

Upvotes: 3

Views: 225

Answers (3)

Matthieu M.
Matthieu M.

Reputation: 300029

Lambdas are actually the right translation. They have exactly the semantic you would wish for, after all, and were described as such by Herb Sutter himself in Complex initialization for a const variable.

If you do not wish to use lambdas, or cannot afford C++11, another solution is to turn to boost::optional:

boost::optional<Foo> foo_;
{
    // init computations
    foo_ = Foo(....);
}
Foo& foo = *foo_;

Upvotes: 1

Alexandre C.
Alexandre C.

Reputation: 56976

What about this:

Foo foo ([]() -> some_type { blah blah; return last_result; } ());

The drawback (outside verbosity) is that you cannot deduce the return type of the lambda, unless everything fits in the return statement. It seems that C++1y will solve this though.

Upvotes: 1

J W
J W

Reputation: 21

This might work:

uint8_t foo[sizeof (Foo)];
do {
  /* declarations and statements */
  new (foo) Foo (/*last result*/);
} while (0);

Then replace every reference to foo with

*((Foo *) foo)

Upvotes: 1

Related Questions