Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C+的C#空合并运算符等价物+; 是否有C++等价的C?零结点算子?我在代码中做了太多的空检查。因此,我们在寻找一种减少空代码量的方法。< p>在C++中没有默认的方法,但是可以写一个:_C#_C++_Null_Null Coalescing Operator - Fatal编程技术网

C+的C#空合并运算符等价物+; 是否有C++等价的C?零结点算子?我在代码中做了太多的空检查。因此,我们在寻找一种减少空代码量的方法。< p>在C++中没有默认的方法,但是可以写一个:

C+的C#空合并运算符等价物+; 是否有C++等价的C?零结点算子?我在代码中做了太多的空检查。因此,我们在寻找一种减少空代码量的方法。< p>在C++中没有默认的方法,但是可以写一个:,c#,c++,null,null-coalescing-operator,C#,C++,Null,Null Coalescing Operator,在C#the??运算符定义为 a ?? b === (a != null ? a : b) < >,C++方法看起来像 Coalesce(a, b) // put your own types in, or make a template { return a != null ? a : b; } 这个怎么样 #define IFNULL(a,b) ((a) == null ? (b) : (a)) 我刚刚发现: 您还可以在C/C++中使用?: 接线员: string pageTi

在C#the??运算符定义为

a ?? b === (a != null ? a : b)
< >,C++方法看起来像

Coalesce(a, b) // put your own types in, or make a template
{
    return a != null ? a : b;
}
这个怎么样

#define IFNULL(a,b) ((a) == null ? (b) : (a))
我刚刚发现:

您还可以在C/C++中使用
?:
接线员:

string pageTitle = getTitle() ?: "Default Title";

使用模板和C++11 lambdas。第一个参数(左侧)只计算一次。仅当第一个参数为false时,才会计算第二个参数(右侧)

模板
TValue合并(TValue lhsValue,TRhsEvaluator evaluateRhs){
返回lhsValue?lhsValue:evaluateRhs();
}
请注意,
if
静态地将提供的表达式强制转换为
bool
,并且指针具有一个内置的
显式运算符bool()const
运算符,该运算符与
!=空PTR

用法示例:

void*const nonZeroPtr=重新解释强制转换(0xF);
void*const otherNonZeroPtr=重新解释强制转换(0xA);

std::cout只想扩展@Samuel Garcia的答案,通过概括模板和添加辅助宏来减少lambda样板的工作量:

#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 (

我希望这会有所帮助。

有一个GNU GCC扩展,允许使用中间操作数缺失的
?:
运算符,请参阅

条件表达式中的中间操作数可以省略。那么如果 第一个操作数为非零,其值为 条件表达式

因此,表达式

x?:y

如果非零,则具有
x
的值;否则
y

这个例子完全等同于

x?x:y

在这种简单的情况下,省略中间操作数的能力 不是特别有用。当它变得有用时,第一个 操作数不包含或可能(如果是宏参数)包含边 效果。然后在中间重复操作数将执行 副作用两次。省略中间操作数已使用该值 计算时没有重新计算的不良影响

此扩展也受的支持。但是,在使用扩展之前,您应该与正在使用的编译器以及代码的可移植性要求进行核对。值得注意的是,MSVC C++编译器不支持<代码>中的省略操作数::./P>
另请参阅相关的StackOverflow讨论。

这里有两个宏,分别复制
?。
运算符。它们也只安全地计算一次操作数:

#define COACALL(a, b) ([&](){ auto val = (a); if (val) (val->b); }());
#define COALESCE(a, b) ([&](){ auto val = (a); return ((val) == NULL ? (b) : (val)); }()) 
这样使用:

COACALL( goodPtr , sayHello() );
COACALL( nullPtr , sayHello() );

COALESCE( nullPtr, goodPtr )->sayHello();
COALESCE( nullPtr, COALESCE( nullPtr, goodPtr ) )->sayHello();

COACALL( COALESCE( nullPtr, goodPtr ), sayHello() );

为了补充提到
?:
运算符(“Elvis运算符”):我有时会将一个helper函数与此运算符一起使用,以获取指针的基本值或
std::optional
或类似类型,这些类型“包装”一个值并进行布尔转换以指示值的存在。例如:

template <typename T>
constexpr T coalesce (std::optional<T> opt) {
    return *opt;
}
template <typename T>
constexpr T coalesce (T fallback) {
    return fallback;
}

std::optional<int> opt1{5};
std::optional<int> opt2;
int val1 = coalesce(opt1 ?: 0);
int val2 = coalesce(opt2 ?: 0);
模板
constexpr T合并(标准::可选选项){
返回*opt;
}
模板
constexpr T合并(T回退){
返回回退;
}
std::可选opt1{5};
std::可选opt2;
int val1=合并(opt1?:0);
int val2=合并(opt2?:0);

唯一的缺点是,这必须小心使用,不会给你一个正确使用静态检查。例如,您可以只执行
合并(opt2)
,而不必执行
?:回退操作,这与执行
*opt2
相同,无需首先检查它是否包含任何内容。因此,
coalesce
这个名称有点误导人,但在我看来,如果使用正确,它看起来是不言自明的(而且相当简洁)。

小心IFNULL(a++,b)是的,我意识到如果你认为a可能是null,你无论如何都要小心。IFNULL(SomeClass.DoSomethingReallyLong(),“”)也会导致问题。很好的一点——我很懒。使用模板方法无疑是一种方法,因为它避免了副作用,并将具有同等的性能(或更好)。我现在要在@McKay的解决方案中添加+1.:-)函数模板不一定具有相同或更好的性能。这种“短路”(除非
a
为空,否则不会计算
b
),而函数的参数总是被计算的。这也是一个好的观点。但是,我认为最常见的用例(至少在C#中,当我使用??操作符时)是a比b更昂贵(例如数据库调用、XML解析)。b通常是一个常数,如0或“”。所以我怀疑模板在大多数情况下都会胜出。另外,除非您知道宏是如何实现的,否则双重执行对宏的调用者来说是不明显的,而函数调用语义是众所周知的,因此任何具有昂贵b的人都知道跳过函数,只需手动创建一个临时变量。有趣的是,我反对我自己的答案…:-)您可以使用lambda进行包装,这样
a
就不会被计算两次
#define IFNULL(a,b)([&](){auto val=(a);return((val)==NULL?(b):(val));}()
在该方法中,即使a不是NULL,也会对b求值。如果b有副作用,这可能是个问题。@Amnon:确实如此。考虑:
p=Coalesce(p,新的int(10))。而且,在C++中,右边的操作数不能为空(在编译时不能检查,因为C++中没有可空类型)。另一方面:C++中是否有这么多的需要,所以不能只键入<代码>?a:b?如果是C++11或更高版本,请使用
nullptr
。无论如何,C/C++中没有
null
,只有
null
在一些头中定义@Lunyx:在
A??B??C
的情况下,
B??C
是第一个
的右操作数。换句话说
template <typename T>
constexpr T coalesce (std::optional<T> opt) {
    return *opt;
}
template <typename T>
constexpr T coalesce (T fallback) {
    return fallback;
}

std::optional<int> opt1{5};
std::optional<int> opt2;
int val1 = coalesce(opt1 ?: 0);
int val2 = coalesce(opt2 ?: 0);