C# null coalescing operator equivalent for c++

主宰稳场 提交于 2019-11-29 03:06:32

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;
}
adamjhilton

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 of y.

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!