I am often using the common
if (Value * value = getValue())
{
// do something with value
}
else
{
// handle lack of value
}
Now, I also often do
QString error = someFunctionReturningAnErrorString(arg);
if (!error.isEmpty())
{
// handle the error
}
// empty error means: no error
That's all fine but I would like the error
variable to be scoped to the if
-block. Is there a nice idiom for that? Obviously, I can just wrap the whole part inside another block.
This, obviously, does not work:
if(QString error = someFunctionReturningAnErrorString(arg), !error.isEmpty())
{
// handle the error
}
// empty error means: no error
And unfortunately (but for good reasons) the QString
cannot be converted to bool, so this does not work either:
if(QString error = someFunctionReturningAnErrorString(arg))
{
// handle the error
}
// empty error means: no error
Any suggestions?
No. There is no idiom like this, and there is no syntax like this!
Besides, you have reached the point at which it is no longer worthwhile to make your code more and more obfuscated.
Simply write it as you do now.
If you really don't want the scope leakage, introduce a new scope:
{
const QString error = someFunctionReturningAnErrorString(arg);
if (!error.isEmpty()) {
// handle the error
}
}
// The above-declared `error` doesn't exist down here
I use this pattern quite a lot, though I've been fairly accused of scope-addiction, so take that as you will.
The only way to use that idiom while still keeping your code understandable is if your function returns an object that is convertible to bool in a way that true
indicates that you want to take the branch and false
means that you do not care about it. Anything else is just going to lead to write-only code.
One such object which may be relevant happens to be boost::optional
. Given:
boost::optional<QString> someFunctionReturningAnErrorString(T arg);
You could use the idiom you want in a natural way:
if (auto error = someFunctionReturningAnErrorString(arg)) {
// ...
}
This also has the added benefit where I'd consider an optional
error message more semantically meaningful than having to check for an empty error message.
There is basically no clean way to do that.
I'd recommend you just define an extra block around the if
, but if you really want to have that exact syntax, a solution could be to declare your own class wrapping QString
:
struct ErrorString
{
ErrorString(QString&& s) : s{move(s)} {}
operator bool() {return !s.isEmpty();}
QString s;
};
And then you could write:
if(ErrorString error = someFunctionReturningAnErrorString(arg))
{
// handle the error
}
// empty error means: no error
But I'm not particularly fond of this solution.
You could use:
for(QString error = someFunctionReturningAnErrorString(arg); !error.isEmpty(); /* too bad 'break' is invalid here */)
{
// handle the error
break;
}
but this is ugly, and makes your code hard to read. So please don't.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With