#define COA(a, b) ([&](){ auto val = (a); return ((val) == NULL ? (b) : (val)); }())
#define COACALL(a, b) ([&](){ auto val = (a); if (val) (val->b); }());
有一个GNU GCC扩展允许在缺少中间操作数的情况下使用?:运算符,请参阅省略操作数的条件。 条件表达式中的中间操作数可以省略。如果第一个操作数非零,则其值为条件表达式的值。 因此,表达式 x ? : y 如果x不为零,则其值为x;否则为y的值。 这个例子完全等同于 x ? x : y 在这种简单的情况下,省略中间操作数的能力并不是特别有用。当第一个操作数确实或可能(如果它是一个宏参数)包含副作用时,它就变得有用了。然后重复中间的操作数将执行两次副作用。省略中间操作数使用已经计算过的值,而不会产生重新计算的不良影响。 clang也支持此扩展。但是,在使用扩展之前,您应该检查您正在使用的编译器和代码的可移植性要求。值得注意的是,MSVC C++编译器不支持?:中的省略操作数。 另请参阅相关的StackOverflow讨论here。
9条答案
按热度按时间jogvjijk1#
我刚发现这个The ?? operator aka the Null Coalescing Operator
你也可以在C/C++中使用
?:
操作符将其作为GNU扩展:h5qlskok2#
在C++中没有默认的方法来做到这一点,但是你可以写一个:
在C#中,??运算符定义为
因此,C++方法看起来像
5rgfhyps3#
使用模板和C++11 lambdas:
请注意,
if
和?
静态地将提供的表达式转换为bool
,并且指针具有内置的explicit operator bool() const
运算符,该运算符等同于!= nullptr
示例用法:
上面的代码只会将
0xf
打印到控制台。右边需要 Package 在lambda中-我们不能避免这个样板。实际上,语言应该提供一个空的合并操作符。
uidvcgyl4#
只是想通过泛化模板并添加辅助宏来扩展@Samuel Garcia的答案,以减少lambda样板:
使用宏,您可以:
希望这能帮上忙。
jrcvhitl5#
这里有两个宏来复制
??
和?.
运算符。这些宏确保:示例用法:
定义:
注意:
COACALL
不返回结果。只能根据需要与void调用或alter一起使用。vbopmzt16#
这个怎么样?
6yjfywim7#
有一个GNU GCC扩展允许在缺少中间操作数的情况下使用
?:
运算符,请参阅省略操作数的条件。条件表达式中的中间操作数可以省略。如果第一个操作数非零,则其值为条件表达式的值。
因此,表达式
x ? : y
如果
x
不为零,则其值为x
;否则为y
的值。这个例子完全等同于
x ? x : y
在这种简单的情况下,省略中间操作数的能力并不是特别有用。当第一个操作数确实或可能(如果它是一个宏参数)包含副作用时,它就变得有用了。然后重复中间的操作数将执行两次副作用。省略中间操作数使用已经计算过的值,而不会产生重新计算的不良影响。
clang也支持此扩展。但是,在使用扩展之前,您应该检查您正在使用的编译器和代码的可移植性要求。值得注意的是,MSVC C++编译器不支持
?:
中的省略操作数。另请参阅相关的StackOverflow讨论here。
nszi6y058#
只是为了补充提到
?:
运算符(“Elvis运算符”)的答案:我有时会使用一个helper函数和这个运算符,它获取指针或std::optional
或类似类型的底层值,这些类型“ Package ”一个值并进行布尔转换以指示值的存在。例如:唯一的缺点是必须小心使用,并且不会为您提供正确使用的静态检查。例如,您可以在没有
?: fallback
的情况下执行coalesce(opt2)
,这与在没有首先检查它是否包含任何内容的情况下执行*opt2
是一样的。因此,coalesce
这个名称有点误导,但在我看来,如果正确使用,它看起来是不言自明的(而且相当整洁)。xuo3flqw9#
提醒:C#合并语义
??
,C#的合并运算符are的语义:这里,
p
是??
运算符的左操作数,q
是右操作数。p
的值可以是可空类型,但q的值必须是不可空类型。如果p
的值是null
,则返回q的值。否则,将返回p
的值。一个C++实现
我们首先注意到C++不能使用
??
作为标识符;预处理器也不愿意让我们用这个名字定义一个宏。所以,让我们使用coalesce
作为标识符。我们需要以某种方式将
coalesce
定义为具有所需语义的中缀运算符。这可以通过运算符重载和宏的组合来实现,以便我们可以编写:下面是一个实现:
在GodBolt上查看它的实际操作。
备注:
q
* 即使不使用也会被 * 求值。可以用短路逻辑编写宏,但它不会是中缀运算符。?:
Elvis-operator,因为它的语义是不同的。它会考虑一个非空的false值作为选择RHS操作数的原因,即false ?: 123
将产生123
,而false ?? 123
是false
使用C#合并语义。std::optional
上实现这个功能,检测nullopt
。如果需要的话,也可以使用一些if-constexpr或tagged-dispatch TMP。