2009-11-23 41 views
16

C#空合并运算符是否有C++等效项?我在我的代码中做了太多的空检查。所以寻找一种方法来减少空代码的数量。C#空合并运算符等效于C++

+7

在GCC中,它是'a?:b',但它不可移植。 – MSalters 2009-11-26 15:36:15

回答

12

没有办法通过默认在C++中要做到这一点,但你可以写一个:

在C#中?运营商被定义为

​​

所以,C++方法看起来像

Coalesce(a, b) // put your own types in, or make a template 
{ 
    return a != null ? a : b; 
} 
+12

在此方法中,即使a不为null,也会评估b。如果b有副作用,这可能是一个问题。 – Amnon 2009-11-23 19:52:16

+3

@Amnon:确实。考虑:'p = Coalesce(p,new int(10));'。另外,它看起来在C#中右手操作数不能为NULL(无法在编译时检查,因为C++中没有可为空的类型?)。另一方面:C++中是否有这么多的需求,以至于你不能只输入'a? a:b;'? – UncleBens 2009-11-23 21:34:01

+1

如果它是C++ 11或更高版本,请使用'nullptr'。无论如何,C/C++中不存在'null',在某些头文件中只定义了'NULL'。 http://stackoverflow.com/questions/1282295/what-exactly-is-nullptr – 2013-09-12 18:52:13

2

这个怎么样?

#define IFNULL(a,b) ((a) == null ? (b) : (a)) 
+2

要小心IFNULL(a ++,b) 是的,我意识到如果你认为可能为空,你会想要提防。 IFNULL(SomeClass.DoSomethingReallyLong(),“”) 也会导致问题。 – McKay 2009-11-23 19:40:18

+0

好点 - 让我懒惰。使用模板方法是确定的方法,因为它避免了副作用,并且具有相同的性能(或更好)。我现在要在@ McKay的解决方案上添加一个+1。 :-) – 2009-11-23 20:27:16

+3

函数模板不一定具有相同或更好的性能。这种“短路”(除非'a'为空,否则不评估'b'),而函数的参数总是被评估。 – 2009-11-23 22:02:09

1

使用模板和C++ 11 lambda表达式。第一个参数(左侧)仅被评估一次。第二个参数(右侧)仅在第一个参数为false时进行评估(注意'if'和'?'静态地将提供的表达式转换为bool,并且指针具有等价的'显式运算符bool()const'以 '!= nullptr')使用

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"; 

将刚刚在控制台打印 '0xf' 的

template<typename TValue, typename TSpareEvaluator> 
TValue 
coalesce(TValue mainValue, TSpareEvaluator evaluateSpare) { 

    return mainValue ? mainValue : evaluateSpare(); 
} 

例。无需编写拉姆达的RHS是样板

[&]() { return <rhs>; } 

的一点点,但它如果通过语言的语法缺乏支持,可以做到最好。

+0

这是提供空合并运算符的相同语义的唯一答案。不过,这可能很少值得大惊小怪。真的,这个功能只需要在语言中。 – 2016-10-15 12:28:30

1

只是想通过要概括的模板,并添加辅助宏扩大@Samuel加西亚的回答削减拉姆达样板:

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

使用宏,你可以:

int* f(); 
int* g(); 
int* h(); 

int* x = COALESCE(f() OR_ELSE g() OR_ELSE h()); 

我希望这可以帮助。