Date: Tue, 11 Apr 2023 15:36:29 +0200
A)
Why not simply
auto BAIL = [p](void)->bool { strcpy(p, "0000000000000000"); return false; };
if ( SUCCESS != fpgaReadInt32(0x00f6, &p32[0]) )
return BAIL();
B)
or create a scope guard (which automatically does the strcpy), and which can be deactivated in the success path.
C)
or put the handling of success/bail into the surrounding function:
// lambda or 'real' function
auto readtest = [p](void)->void {
if ( (SUCCESS != fpgaReadInt32(0x00f2, &p32[0])) || (0 ==
(p32[0] & 1)) ) return false;
if ( SUCCESS != fpgaReadInt32(0x00f6, &p32[0]) ) return false;
if ( SUCCESS != fpgaReadInt32(0x00fa, &p32[1]) ) return false;
}
if (!readtest())
strcpy(...);
return false;
}
sprinf(...)
return true;
-----Ursprüngliche Nachricht-----
Von:Frederick Virchanza Gotham via Std-Proposals <std-proposals_at_[hidden]>
Gesendet:Di 11.04.2023 15:17
Betreff:[std-proposals] long return lambda
An:std-proposals <std-proposals_at_[hidden]>;
CC:Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>;
Today I wrote the following function for a microcontroller:
bool Serial(char *const p)
{
# define BAIL { strcpy(p, "0000000000000000"); return false; }
int32_t p32[2u];
if ( (SUCCESS != fpgaReadInt32(0x00f2, &p32[0])) || (0 ==
(p32[0] & 1)) ) BAIL
if ( SUCCESS != fpgaReadInt32(0x00f6, &p32[0]) ) BAIL
if ( SUCCESS != fpgaReadInt32(0x00fa, &p32[1]) ) BAIL
sprintf(p + 0u, "%08lx", static_cast<long unsigned>(p32[0]));
sprintf(p + 16u, "%08lx", static_cast<long unsigned>(p32[1]));
return true;
# undef BAIL
}
I would have liked to use a lambda instead of a macro there, but then
I would have to write:
bool Serial(char *const p)
{
auto BAIL = [p](void)->void { strcpy(p, "0000000000000000"); };
int32_t p32[2u];
if ( (SUCCESS != fpgaReadInt32(0x00f2, &p32[0])) || (0 ==
(p32[0] & 1)) ) { BAIL(); return false; }
if ( SUCCESS != fpgaReadInt32(0x00f6, &p32[0]) ) { BAIL();
return false; }
if ( SUCCESS != fpgaReadInt32(0x00fa, &p32[1]) ) { BAIL();
return false; }
sprintf(p + 0u, "%08lx", static_cast<long unsigned>(p32[0]));
sprintf(p + 16u, "%08lx", static_cast<long unsigned>(p32[1]));
return true;
}
So I thinking, what if we had a 'long return lamda'? The return
statement from a 'long return lambda' is treated as a return statement
from the enclosing function. As follows:
bool Serial(char *const p)
{
auto BAIL = [p](void) -> long return bool { strcpy(p,
"0000000000000000"); return false; };
int32_t p32[2u];
if ( (SUCCESS != fpgaReadInt32(0x00f2, &p32[0])) || (0 ==
(p32[0] & 1)) ) BAIL();
if ( SUCCESS != fpgaReadInt32(0x00f6, &p32[0]) ) BAIL();
if ( SUCCESS != fpgaReadInt32(0x00fa, &p32[1]) ) BAIL();
sprintf(p + 0u, "%08lx", static_cast<long unsigned>(p32[0]));
sprintf(p + 16u, "%08lx", static_cast<long unsigned>(p32[1]));
return true;
}
Of course, you wouldn't be able to store one of these lambdas inside a
normal 'std::function', you'd need to store it inside a
'std::long_return_function' instead.
A few important points:
(1) The return type of a 'long return lambda', if not omitted, must be
implicitly-convertible to the return type of the enclosing function.
(2) You cannot analyse the return value from a 'long return lambda'
inside the enclosing function. For example the initialisation of a
variable inside the enclosing function cannot involve the invocation
of a 'long return lambda', so the following isn't valid:
int MyFunc(void)
{
auto monkey = []()->long return { return 5; }
int i = monkey(); // ill-formed - compiler must issue diagonstic
}
(3) However you can analyse the return value higher up the function
call hierarchy:
int Func2(void)
{
auto Bail = []() -> long return int { return 5; }
// int i = Bail(); - This would be invalid
Bail();
}
int Func(void)
{
int i = Func2(); // This is valid
}
--
Std-Proposals mailing list
Std-Proposals_at_[hidden]
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2023-04-11 13:36:31