Is there a C++ equivalent for C# null coalescing operator? I am doing too many null checks in my code. So was looking for a way to reduce the amount of null code.
There isn't a way to do this by default in C++, but you could write one:
in C# the ?? operator is defined as
a ?? b === (a != null ? a : b)
So, the C++ method would look like
Coalesce(a, b) // put your own types in, or make a template
{
return a != null ? a : b;
}
I just found this: The ?? operator aka the Null Coalescing Operator
You also have it in C/C++ as a GNU extension using the
?:
operator :string pageTitle = getTitle() ?: "Default Title";
Using templates and C++11 lambdas. The first argument (left-hand side) is only evaluated once. The second argument (right-hand side) is only evaluated if the first is false (note that 'if' and '?' statically cast the provided expression to bool, and that pointers have 'explicit operator bool() const' that is equalivent to '!= nullptr')
template<typename TValue, typename TSpareEvaluator>
TValue
coalesce(TValue mainValue, TSpareEvaluator evaluateSpare) {
return mainValue ? mainValue : evaluateSpare();
}
Example of use
void * const nonZeroPtr = reinterpret_cast<void *>(0xF);
void * const otherNonZeroPtr = reinterpret_cast<void *>(0xA);
std::cout << coalesce(nonZeroPtr, [&] () { std::cout << "Never called"; return otherNonZeroPtr; }) << "\n";
Will just print '0xf' in the console. Having to write a lambda for the rhs is a little bit of boilerplate
[&] () { return <rhs>; }
but it's the best that one can do if one lacks support by the language syntax.
How about this?
#define IFNULL(a,b) ((a) == null ? (b) : (a))
Just want to expand @Samuel Garcia's answer by generalising the template and adding helper macros to cut down on lambda boilerplate:
#include <utility>
namespace coalesce_impl
{
template<typename LHS, typename RHS>
auto coalesce(LHS lhs, RHS rhs) ->
typename std::remove_reference<decltype(lhs())>::type&&
{
auto&& initialValue = lhs();
if (initialValue)
return std::move(initialValue);
else
return std::move(rhs());
}
template<typename LHS, typename RHS, typename ...RHSs>
auto coalesce(LHS lhs, RHS rhs, RHSs ...rhss) ->
typename std::remove_reference<decltype(lhs())>::type&&
{
auto&& initialValue = lhs();
if (initialValue)
return std::move(initialValue);
else
return std::move(coalesce(rhs, rhss...));
}
}
#define COALESCE(x) (::coalesce_impl::coalesce([&](){ return ( x ); }))
#define OR_ELSE ); }, [&](){ return (
Using the macros, you can just:
int* f();
int* g();
int* h();
int* x = COALESCE( f() OR_ELSE g() OR_ELSE h() );
I hope this helps.
There is a GNU GCC extension that allows using ?:
operator with middle operand missing, see Conditionals with Omitted Operands.
The middle operand in a conditional expression may be omitted. Then if the first operand is nonzero, its value is the value of the conditional expression.
Therefore, the expression
x ? : y
has the value of
x
if that is nonzero; otherwise, the value ofy
.This example is perfectly equivalent to
x ? x : y
In this simple case, the ability to omit the middle operand is not especially useful. When it becomes useful is when the first operand does, or may (if it is a macro argument), contain a side effect. Then repeating the operand in the middle would perform the side effect twice. Omitting the middle operand uses the value already computed without the undesirable effects of recomputing it.
This extension is also supported by clang. However, you should check with the compiler you're using and portability requirements for your code before using the extension. Notably, MSVC C++ compilers do not support omitted operands in ?:
.
See also related StackOverflow discussion here.
来源:https://stackoverflow.com/questions/1785426/c-sharp-null-coalescing-operator-equivalent-for-c