Lambda's in member initializer lists - style question

W

Werner

Hi All,

I've found an interesting use for lambdas in member initializer
lists, and I've wondered if this would be frowned upon from a style
perspective:

Plot::plot()
: curve_( []( Plot& plot )
{
std::unique_ptr<Curve> curve( new Curve );
curve->setZ_Order( 20 );
curve->associate( plot );
return curve;
}( *this ),
etc...
{
}

as opposed to:

Plot::plot()
: curve_( new Curve )
{
//Initialization seperated from creation...
initialiseCurve();
}

I like the idea of using the lambda (or a creation function)
because if initialization fails, creation should too, and then
it would not benefit to create the rest of the object.

OTOH, inter-dependencies may exist between objects:

Widget::Widget()
: plot_(...),
curve_( []( Plot& plot ) //Curve depends on plot...
{
std::unique_ptr<Curve> curve( new Curve );
curve->setZ_Order( 20 );
curve->associate( plot );
return curve;
}( *plot_ ),
etc...
{
}

This creates the risk that plot does not exist, especially if
member declaration order is different to the order in the
member initializer list. On the other hand most compilers
do warn about this kind of thing.

Any thoughts on this style issue?

Kind Regards,

Werner
 
A

Alain Ketterlin

Werner said:
I've found an interesting use for lambdas in member initializer
lists, and I've wondered if this would be frowned upon from a style
perspective:

Plot::plot()
: curve_( []( Plot& plot )
{
std::unique_ptr<Curve> curve( new Curve );
curve->setZ_Order( 20 );
curve->associate( plot );
return curve;
}( *this ),
etc...
{
}

as opposed to:

Plot::plot()
: curve_( new Curve )
{
//Initialization seperated from creation...
initialiseCurve();
}

Sorry, but why isn't that:

Plot::plot() : curve_(20,this), etc...
{
}

I mean, your lambda doesn't do anything but setting up a Curve object,
so why is this not part of Curve's construction?

OTOH, inter-dependencies may exist between objects:

Widget::Widget()
: plot_(...),
curve_( []( Plot& plot ) //Curve depends on plot...
{
std::unique_ptr<Curve> curve( new Curve );
curve->setZ_Order( 20 );
curve->associate( plot );
return curve;
}( *plot_ ),
etc...
{
}

This creates the risk that plot does not exist, especially if
member declaration order is different to the order in the
member initializer list.

This can't be, as far as I know. Members have to be initialized in the
order with which they are declared.

-- Alain.
 
W

Werner

Sorry, but why isn't that:



Plot::plot() : curve_(20,this), etc...

{

}

I mean, your lambda doesn't do anything but setting up a Curve object,
so why is this not part of Curve's construction?

- You don't necessarily have control over curve's
construction.
- In the above event, you could create a class in an anon
namespace that is just responsible for the construction itself:
namespace {
class MyCurve : OrignalCurve
{
MyCurve( appropriate members for proper construction... )
};
}

but IMhO if only required once, the lambda is less work...
This can't be, as far as I know. Members have to be initialized in the
order with which they are declared.

Yes, they have to be:

class X
{
....
Curve* curve_;
Plot* plot_;
....
};

X::X()
: plot_( new Plot ),
curve( new Curve( *plot_ ) )
{ }

The compiler is not forced to give a diagnostic
in this case, and plot has not been initialized yet,
because members [are] initialized in the order they
are declared, and not in the order specified in
the member initializer list.

Regards,

Werner
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,189
Members
46,734
Latest member
manin

Latest Threads

Top