C++等效于 C# 的 "?." 空条件运算符

C++ equivalent for C#'s "?." null conditional operator

本文关键字:条件运算符 C++      更新时间:2023-10-16

在C#中有一个空条件运算符?.:

MyObject o = null;
o?.doSomeThing();

意思是:

if(o != null)
o.doSomeThing();

我想在C++中有类似的东西:

MyObject* o = nullptr;
o?>doSomeThing(); // or o?->

如果一个人写这样的话,这是非常有用的:

o?.getO()?.getO()?.doSomeThing();

所以我有两个问题:

  1. 今天,我们使用宏进行单行条件执行。在C++14中,有没有一种不使用宏的简便方法
  2. 任何地方都有讨论或建议吗?我什么也没找到

不,没有语法可以做到这一点,也没有办法创建所述语法。

同样,也没有建议(据我所知(添加它

相反,你可以自己写下空检查,或者更好的是,通过重组代码来减少可以为"空"的地方的数量,这样你就不需要它们了。

WRT问题#1:

CCD_ 2和CCD_ 3函数是宏函数的类型安全C++等价物。它们不能保证内联你的代码,但它们允许编译器根据需要进行复制,而积极的编译器会为你进行内联。许多标准库类都做出了这种假设(例如std::vector<T>::size()(。

编辑:好吧,你们很有诚意,但很公平。这里有一种使用它来解决这个问题的方法:

编辑:根据要求更新为用C++14编译。我知道这已经被标记为重复,没有人会看它,但其他链接只是C++17。它还终止于非指针成员,并返回指向它们的指针,这更符合C#,后者将值类型转换为Nullable。

#include <cstdio>
#include <type_traits>
template <typename Class>
struct SafePtrImpl { 
Class* ptr;
SafePtrImpl(Class* ptr) : ptr(ptr) { }
template <typename TClass, typename TResult, std::enable_if_t<std::is_pointer<TResult>::value, std::nullptr_t> = nullptr>
inline SafePtrImpl<
std::remove_pointer_t<
std::remove_reference_t<
TResult>>> operator ->*(TResult TClass::*member) {
return SafePtr(ptr ? ptr->*member : nullptr);
}
template <typename TClass, typename TResult, std::enable_if_t<!std::is_pointer<TResult>::value, std::nullptr_t> = nullptr>
inline TResult* operator ->*(TResult TClass::*member) {
return ptr ? &(ptr->*member) : nullptr;
}
};
template <typename TClass>
SafePtrImpl<TClass> SafePtr(TClass* ptr) { return SafePtrImpl<TClass>(ptr); }
// --
struct Foo {
int x;
};
struct Bar {
Foo* y;
};
int main() {
Foo a { 42 };
Bar b { &a };
Bar c { nullptr };
Bar* d = nullptr;
int* b_y_x = SafePtr(&b)->*&Bar::y->*&Foo::x;
int* c_y_x = SafePtr(&c)->*&Bar::y->*&Foo::x;
int* d_y_x = SafePtr(d)->*&Bar::y->*&Foo::x;
printf("b: %08x %dn", b_y_x, *b_y_x);
printf("c: %08xn", c_y_x);
printf("d: %08xn", d_y_x);
return 0;
}

https://godbolt.org/z/RYZ1EV

输出:

b: 3aa42aec 42
c: 00000000
d: 00000000