Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Assigning reference with complex value w/o lambda

34 views
Skip to first unread message

Marcel Mueller

unread,
Sep 5, 2015, 7:22:51 AM9/5/15
to
I have a code fragment to assign a local reference. Because references
must be initialized immediately I used a lambda as work around.

enum mux
{ M_R0,
M_R1
//...
};
enum ctx
{ IC_NONE,
IC_MUL,
IC_B
//...
};

ctx InstCtx;
mux MuxAA;
mux MuxAB;
mux MuxMA;
mux MuxMB;

mux& ret = [this]() -> mux&
{ switch (InstCtx & (IC_MUL|IC_B))
{case IC_NONE:
return MuxAA;
case IC_B:
return MuxAB;
case IC_MUL:
return MuxMA;
default:
return MuxMB;
}
}();

Is this possible without the lambda (or the ugly ?: operator)?
Does the lambda cause any runtime overhead?

In old style C a variable of type mux* and a switch does the job.
But I avoid raw pointer in C++ where possible.


Marcel

Öö Tiib

unread,
Sep 5, 2015, 1:58:11 PM9/5/15
to
Your pseudocode above leaves impression that you use reference to
local non-static variable as return value ('ret'?). If that is true
then that is obviously defect. Write real code that does compile
instead of such pseudocode; it is just few lines more but improves
communications with others tremendously.

Sure, complex logic (like that ?: chain) can be often replaced with
lookup table or ordinary inline function or member function.

I don't feel lambda is needed for that. I use lambda when I need to
store or pass (as argument or return value) a function that is
already instrumented with some of input data.

Real compilers optimize these very well and often optimize code that uses
references better than code that uses pointers. C++ standard does
not guarantee anything of it. If performance matters then just profile
things at end of life-cycle during stress- and limitation-testing
regardless of what style you use.

>
> In old style C a variable of type mux* and a switch does the job.
> But I avoid raw pointer in C++ where possible.

Makes sense! 'mux&' has to be initialized, can not be changed and
may not be null and its declaration and usage syntax is more terse
than that of 'mux*const'.

Luca Risolia

unread,
Sep 5, 2015, 4:03:49 PM9/5/15
to
Il 05/09/2015 13:22, Marcel Mueller ha scritto:
> I have a code fragment to assign a local reference. Because references
> must be initialized immediately I used a lambda as work around.

> mux& ret = [this]() -> mux&
> { switch (InstCtx & (IC_MUL|IC_B))

auto& ret = [this]() noexcept -> mux&

or

decltype(auto) ret = [this]() noexcept -> mux& // C++14

the approach is ok.

Marcel Mueller

unread,
Sep 5, 2015, 4:04:48 PM9/5/15
to
On 05.09.15 19.57, Öö Tiib wrote:
> Your pseudocode above leaves impression that you use reference to
> local non-static variable as return value ('ret'?). If that is true
> then that is obviously defect.

No. Logically the function really returns a value in one of the Mux
fields, but the signature returns void.

> Write real code that does compile
> instead of such pseudocode; it is just few lines more but improves
> communications with others tremendously.

Well, the code fragment is copied from a source file, in fact a GPU
assembler, but without the context of the surrounding (rather large)
class it makes no much sense.

But you are right. Only a few more lines made it compile

enum mux
{ M_R0,
M_R1
//...
};
enum ctx
{ IC_NONE,
IC_MUL,
IC_B
//...
};

struct test
{
ctx InstCtx;
mux MuxAA;
mux MuxAB;
mux MuxMA;
mux MuxMB;

void method()
{
mux& ret = [this]() -> mux&
{ switch (InstCtx & (IC_MUL|IC_B))
{case IC_NONE:
return MuxAA;
case IC_B:
return MuxAB;
case IC_MUL:
return MuxMA;
default:
return MuxMB;
}
}();

ret = M_R1; // example
}
};

int main()
{
test t;
t.InstCtx = IC_B; // example
t.method(); // write to MuxAB

return 0;
}

> Real compilers optimize these very well and often optimize code that uses
> references better than code that uses pointers. C++ standard does
> not guarantee anything of it. If performance matters then just profile
> things at end of life-cycle during stress- and limitation-testing
> regardless of what style you use.

Performance is no killer in /this/ case. I just wanted to know what is
going on and whether there is prettier solution.

Just had a look to the assembler code. It made absolutely no difference
whether I use the lambda function or the old C style pointer syntax
(with optimizations).
Only when I create a dispatch table of type static mux test::*const
map[] on my own a more efficient code (shorter, no conditional branches)
is generated.


>> In old style C a variable of type mux* and a switch does the job.
>> But I avoid raw pointer in C++ where possible.
>
> Makes sense! 'mux&' has to be initialized, can not be changed and
> may not be null and its declaration and usage syntax is more terse
> than that of 'mux*const'.

Indeed.

Furthermore, I had to change several line of code in this case. The
function previously returned mux (no reference) and the assignment was
up the the caller which usually knows the right target field. But this
raised problems of deep sub functions that rely on the value to be
assigned sooner to perform some consistency checks. So I refactored the
code to identify the target field from the invocation context InstCtx.


Marcel

Paavo Helde

unread,
Sep 5, 2015, 4:13:34 PM9/5/15
to
Marcel Mueller <news.5...@spamgourmet.org> wrote in
news:msfhsk$nva$1...@gwaiyur.mb-net.net:
I don't understand; if MuxAA et al are member variables and you do not
like a lambda, what prevents you from writing a member function returning
a reference to the needed member variable?

p.
0 new messages