This question already has answers here:
What is a lambda expression in C++11?
(10 answers)
Closed 1 year ago.
I'm writing a (my own language) to C++ transpiler. I'd like to be able to offer a kind of virtual sub function that is transpiled into being part of the C++ code in the same scope in which it is called.
Here is an example of the type of C++ code I'd want to generate:
if (a == {if (getValue(d) == 5) { long r = next(); next(); return r; } else return 0;})
dosomething();
It says if a is equal to the result of what's in the brackets, then dosomething().
You can see the idea is to inline a function within an expression. Yes that could be done by allowing the compiler to inline, but in this case I want to keep access to the variables in the outer scope, which I would lose if it actually were another function.
Any decent way to do this?
If I correctly get what you are doing, you can simply use lambda expression here. This of course requires C++11
if (a ==
[&] () {
if (getValue(d) == 5) {
long r = next();
next();
return r;
} else {
return 0;
}
}()) {
dosomething();
}
If you are writing translator/transpiler you may want to try more explicit capture list than this generic [&].
I have an enum with one undefined and two user values:
class enum E
{
UNDEFINED,
VALUE1,
VALUE2
};
I want to add VALUE3 but I'm worried there's a lot of code like:
assert(val != E::UNDEFINED);
if(val == E::VALUE1)
{
}
else
{
// Without an assert this wrongly assumes E::VALUE2
}
and:
something = (val == E::VALUE1) ? a : b; // last part assumes E::VALUE2
I like that compilers warn against switch statements not handling all enumerations and wondered if there is anything similar to show all instances of the above?
I'm concerned I won't find and update all instances of the above.
Compiler is Clang
Enums are not restricted to the values you give names to. From cppreference (formatting is mine):
An enumeration is a distinct type whose value is restricted to a range of values (see below for details),
which may include several explicitly named constants ("enumerators"). The values of the constants are values of an integral type known as the underlying type of the enumeration.
The "below details" explain how the enums underlying type is determined. Out of this range we (usually) give names only to some values as in:
enum foo {A,B,C};
int main() {
foo x = static_cast<foo>(42);
}
This code is completely fine. x has an underlying value of 42. There is no name for the value but this doesn't really matter... unless you assume that it does.
That wrong assumption is made by this code:
assert(val != E::UNDEFINED);
if(val == E::VALUE1)
{
}
else
{
// Without an assert this wrongly assumes E::VALUE2
}
This code is what needs to be fixed (independent of whether you add a new named constant to the enum or not).
Now for a more serious trial to answer the question...
There is no way to get a warning when a chain of if-else does not cover all enum values. What you can do is to turn all if-else uses of the enum into errors. Consider what actually happens here:
if (x == E::VALUE1) do_something();
switch(x) {
case E::VALUE1 : return 1;
}
In the if statement we call operator==(foo,foo); its return value either is a bool or is implicitly converted to one. With the switch none of this is needed. We can make use of this to turn if-else usages of the enum into errors. Bear with me I will explain in two steps. First lets create a compiler error for if( x == E::VALUE1):
class helper {
operator bool(){ return false;}
};
helper operator==(E,E){
return {};
}
Now if (x == E::VALUE1) calls helper operator==(E,E), thats fine. Then the result is converted to bool, and that fails because the conversion is private. Using the enum in a switch is still ok and you can rely on compiler errors / warnings. The basic idea is just to have something that only fails to compile when called (in the wrong/right context). (Live Demo).
The drawback is that also all other used of operator== are broken. We can fix them by modifying the helper and the call sites:
#include <type_traits>
enum E {VALUE1};
struct helper {
bool value;
private:
operator bool(){ return false;}
};
helper operator==(E a,E b){
return {
static_cast<std::underlying_type_t<E>>(a) == static_cast<std::underlying_type_t<E>>(b)
};
}
int main() {
E x{VALUE1};
//if ( x== E::VALUE1); // ERROR
bool is_same = (x == E::VALUE1).value;
switch(x) {
case E::VALUE1 : return 1;
}
}
Yes it is a major inconvenience to have to write .value, but in this way you can turn all uses of the enum in ifs into errors while everything else will still compile. Also note that you have to make sure to cover all cases you want to catch (eg !=,<, etc).
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I'm working on a Boolean function in C/C++ that verifies multiple conditions (that are Boolean functions themselves) and only returns true if all of them are true.
Time ago I started using Guard Clauses instead of nested ifs, even though it required having multiple returns like follows:
bool foo(){
//some initialization
if( !condition_1() ){
return false;
}
if( !condition_2() ){
return false;
}
...
if( !condition_n() ){
return false;
}
return true;
}
But now I'm asking my self if is it a good alternative to use only one return with Boolean logic, for example:
bool foo(){
//some initialization
return condition_1() && condition_2() && ... && condition_n() ;
}
I don't have any code to run after the guards and there are only a few of them,
so the return statement is not that crowded and the code is not difficult to read. The idea is to avoid nested ifs and use only one exit point in my function.
I tested the code and it works fine, even if condition_1() makes some changes in condition_2(). So I understand that the guard clause code and this version are equivalent and the execution order is maintained form left to right. Is that correct? Are there any hidden differences that make the two versions not 100% equivalent?
Thanks!
You new approach is good, depending if you want to do more than just concat bool operations, it could be useful for maintenance and readability to use a local.
bool foo(){
//some initialization
bool returnCondition = condition_1() &&
condition_2() &&
condition_3() &&
.... &&
condition_n();
return returnCondition;
}
By the way, there is nothing such as the best option.
Indeed, if your objective is code obfuscation, your first option is better than the 2nd.
Technically the two methods you use are correct in case of the functions condition_n() is used only for checking.
But if you need to change something inside them based on a condition of something it will be a problem.
The Best Practice for writing a function body is as follows:
define the default return value
some processing
return the result
Let's rewrite the above function :
bool foo(){
//some initialization
bool ret = true;
if(condition_1() == false){
ret = false;
}
else if(condition_2() == false){
ret = false;
}
...
else if(condition_n() == false){
ret = false;
}
return ret;
}
I am trying make ternary operator work with lambda. Following is the logic that I want to cast into a ternary operation
if (boolean_condition_var == false) {
RandomMethod();
}
// From here some logic to execute
int i = 0;
// blah blah logic
Following is how I am trying to make it work after reading through this link.
boolean_condition_var == false ? RandomMethod() : std::function<void(void)>([this](){
// execute some logic here
int i = 0;
//blah blah logic
});
But I am getting the following error:
Issue:
error: left operand to ? is void, but right operand is of type 'std::function<void ()>'
boolean_condition_var == false ? RandomMethod() : std::function<void(void)>([this](){ int i = 0; });
Question:
How can I pass a lambda into the second clause of my ternary operator?
Since you are not calling the lambda, it makes little sense to create it. What you are trying to do is equivalent to
boolean_condition_var ? void(0) : RandomMethod();
On the other hand, if you want to call the lambda, use the call operator:
boolean_condition_var? ([this](){...your code...}) ( ) : RandomMethod();
// ^
// |
//--------------------------------------------------+
There's no need to cast anything to std::function.
A plain old if-then-else statement would be more welcome here.
On the third hand, if you want your ternary operator to return a callable, you probably need something like
using voidf = std::function<void(void)>;
auto result = boolean_condition_var?
voidf([this](){...your code...}):
voidf([this](){RandomNethod();});
.... result();
Capturing boolean_condition_var by value and moving the condition into the (now single) lambda could be more readable and more efficient though.
How can I pass a lambda into the second clause of my ternary operator?
Using comma operator ?
boolean_condition_var == false
? (RandomMethod(), 0)
: (std::function<void(void)>([this](){ /*...*/ })(), 0);
Or, I suppose better,
std::function<void(void)> logicElse { [this](){ /*...*/ } };
boolean_condition_var == false
? (RandomMethod(), 0)
: (logicElse(), 0);
Sometimes, an if statement can be rather complicated or long, so for the sake of readability it is better to extract complicated calls before the if.
e.g. this:
if (SomeComplicatedFunctionCall() || OtherComplicatedFunctionCall())
{
// do stuff
}
into this
bool b1 = SomeComplicatedFunctionCall();
bool b2 = OtherComplicatedFunctionCall();
if (b1 || b2)
{
//do stuff
}
(provided example is not that bad, it's just for illustration... imagine other calls with multiple arguments, etc.)
But with this extraction I lost the short circuit evaluation (SCE).
Do I really lose SCE every time? Is there some scenario where the compiler is allowed to "optimize it" and still provide SCE?
Are there ways of keeping the improved readability of the second snippet without losing SCE?
One natural solution would look like this:
bool b1 = SomeCondition();
bool b2 = b1 || SomeOtherCondition();
bool b3 = b2 || SomeThirdCondition();
// any other condition
bool bn = bn_1 || SomeFinalCondition();
if (bn)
{
// do stuff
}
This has the benefits of being easy to understand, being applicable to all cases and having short circuit behaviour.
This was my initial solution: A good pattern in method calls and for-loop bodies is the following:
if (!SomeComplicatedFunctionCall())
return; // or continue
if (!SomeOtherComplicatedFunctionCall())
return; // or continue
// do stuff
One gets the same nice performance benefits of shortcircuit evaluation, but the code looks more readable.
I tend to break down conditions onto multiple lines, i.e.:
if( SomeComplicatedFunctionCall()
|| OtherComplicatedFunctionCall()
) {
Even when dealing with multiple operators (&&) you just need to advance indention with each pair of brackets. SCE still kicks in - no need to use variables. Writing code this way made it much more readible to me for years already. More complex example:
if( one()
||( two()> 1337
&&( three()== 'foo'
|| four()
)
)
|| five()!= 3.1415
) {
If you have long chains of conditions and what to keep some of the short-circuiting, then you could use temporary variables to combine multiple conditions. Taking your example it would be possible to do e.g.
bool b = SomeComplicatedFunctionCall() || OtherComplicatedFunctionCall();
if (b && some_other_expression) { ... }
If you have a C++11 capable compiler you could use lambda expressions to combine expressions into functions, similar to the above:
auto e = []()
{
return SomeComplicatedFunctionCall() || OtherComplicatedFunctionCall();
};
if (e() && some_other_expression) { ... }
1) Yes, you no longer have SCE. Otherwise, you would have that
bool b1 = SomeComplicatedFunctionCall();
bool b2 = OtherComplicatedFunctionCall();
works one way or the other depending if there is an if statement later. Way too complex.
2) This is opinion based, but for reasonably complex expressions you can do:
if (SomeComplicatedFunctionCall()
|| OtherComplicatedFunctionCall()) {
If it ways too complex, the obvious solution is to create a function that evaluates the expression and call it.
You can also use:
bool b = someComplicatedStuff();
b = b || otherComplicatedStuff(); // it has to be: b = b || ...; b |= ...; is bitwise OR and SCE is not working then
and SCE will work.
But it's not much more readable than for example:
if (
someComplicatedStuff()
||
otherComplicatedStuff()
)
1) Do I really lose SCE every time? Is compiler is some scenario allowed to "optimize it" and still provide SCE?
I don't think such optimization is allowed; especially OtherComplicatedFunctionCall() might have some side effects.
2) What is the best practice in such situation? Is it only possibility (when I want SCE) to have all I need directly inside if and "just format it to be as readable as possible" ?
I prefer to refactor it into one function or one variable with a descriptive name; which will preserve both short circuit evaluation and readability:
bool getSomeResult() {
return SomeComplicatedFunctionCall() || OtherComplicatedFunctionCall();
}
...
if (getSomeResult())
{
//do stuff
}
And as we implement getSomeResult() based on SomeComplicatedFunctionCall() and OtherComplicatedFunctionCall(), we could decompose them recursively if they're still complicated.
1) Do I really lose SCE every time? Is compiler is some scenario
allowed to "optimize it" and still provide SCE?
No you don't, but it's applied differently:
if (SomeComplicatedFunctionCall() || OtherComplicatedFunctionCall())
{
// do stuff
}
Here, the compiler won't even run OtherComplicatedFunctionCall() if SomeComplicatedFunctionCall() returns true.
bool b1 = SomeComplicatedFunctionCall();
bool b2 = OtherComplicatedFunctionCall();
if (b1 || b2)
{
//do stuff
}
Here, both functions will run because they have to be stored into b1 and b2. Ff b1 == true then b2 won't be evaluated (SCE). But OtherComplicatedFunctionCall() has been run already.
If b2 is used nowhere else the compiler might be smart enough to inline the function call inside the if if the function has no observable side-effects.
2) What is the best practice in such situation? Is it only possibility
(when I want SCE) to have all I need directly inside if and "just
format it to be as readable as possible" ?
That depends.
Do you need OtherComplicatedFunctionCall() to run because of side-effects or the performance hit of the function is minimal then you should use the second approach for readability. Otherwise, stick to SCE through the first approach.
Another possibility that short circuits and has the conditions in one place:
bool (* conditions [])()= {&a, &b, ...}; // list of conditions
bool conditionsHold = true;
for(int i= 0; i < sizeOf(conditions); i ++){
if (!conditions[i]()){;
conditionsHold = false;
break;
}
}
//conditionsHold is true if all conditions were met, otherwise false
You could put the loop into a function and let the function accept a list of conditions and output a boolean value.
Very strange: you are talking about readability when nobody mentions the usage of comment within the code:
if (somecomplicated_function() || // let me explain what this function does
someother_function()) // this function does something else
...
In top of that, I always preceed my functions with some comments, about the function itself, about its input and output, and sometimes I put an example, as you can see here:
/*---------------------------*/
/*! interpolates between values
* #param[in] X_axis : contains X-values
* #param[in] Y_axis : contains Y-values
* #param[in] value : X-value, input to the interpolation process
* #return[out] : the interpolated value
* #example : interpolate([2,0],[3,2],2.4) -> 0.8
*/
int interpolate(std::vector<int>& X_axis, std::vector<int>& Y_axis, int value)
Obviously the formatting to use for your comments may depend on your development environment (Visual studio, JavaDoc under Eclipse, ...)
As far as SCE is concerned, I assume by this you mean the following:
bool b1;
b1 = somecomplicated_function(); // let me explain what this function does
bool b2 = false;
if (!b1) { // SCE : if first function call is already true,
// no need to spend resources executing second function.
b2 = someother_function(); // this function does something else
}
if (b1 || b2) {
...
}
Readability is necessary if you work in a company and your code will be read by someone else. If you write a program for yourself, it is up to you if you want to sacrifice performance for the sake of comprehensible code.