C#には2つのタイプのヌル伝播があります。最初はあなたが記述した通りです。foo
がnullの場合はnullを返しますが、foo
がnullでない場合はfoo->bar
を返します。
これはあまり畳み込まれていないか、C++で既に読みにくいです。
return (foo) ? (foo->bar) ? foo->bar->baz : nullptr : nullptr;
あなたが、私は上記のそれを持っている方法は、条件付きインラインを入れ子にできるようになり、それのマクロを作ることができないように思われます。
#define Maybe(X, Y) (X)?X->Y:nullptr
// Attempted nested usage:
return Maybe(foo, Maybe(foo->bar, baz));
// ^VS2015 complains here saying "Expected a member name".
しかし、マクロがどのように長ったらしい与えられたが、それが働いた場合でも、私はそれが最初に使用条件インラインになりますどのように優れた表示されません。
しかし、Mooing Duck氏の答えで指摘されている「ダブルコール」問題を回避するテンプレートソリューションもあります。
template<typename T_Return, typename T_X, T_Return* T_X::*Y>
T_Return* Maybe(T_X* pX)
{
return (pX) ? pX->*Y : nullptr;
}
//Usage:
// Type is required, so assume the struct Foo contains a Bar* and Bar contains a Baz*.
return Maybe<Baz, Bar, &Bar::baz>(Maybe<Bar, Foo, &Foo::bar(foo));
もちろん、これは要件を満たしていますが、それは不合理で鈍いです。
しかし、「else」の大文字と小文字を区別する必要がないことを意味する、メソッドの呼び出しに使用される2番目のタイプのNull Propagationがあります。ことができますC#で
// C# code here.
if(foo != null) { foo.Bar(); }
場所::それは相当である。これは、マクロを使用して複製しようとする方がはるかに簡単な機能です
foo?.Bar()
、それは通常の構文とのより良い「フィット」。
// C++ Null Propagation
#define Maybe(X) if (auto tempX = (X)) tempX
//Usage
Maybe(GetFoo())->Bar();
//Or for setting a variable:
Maybe(GetFoo()->bar = new Bar();
これは?:略語を使用していないため動作し、代わりに通常のインラインif文を使用しています。
これは、メソッドを呼び出したりメンバを設定する目的のみがあることに注意してください。
あなたが本当に永続している場合は、しかし、あなたが何かを行うことができます:にインライン化することができ
#define ReturnMaybe(X, Y) auto tempX = X; \
if (tempX != nullptr) \
{ \
return tempX->Y; \
} \
else \
{ \
return nullptr; \
} \
:
#define ReturnMaybe(X, Y) auto tempX = X; if(tempX) { return tempX->Y; }else{return nullptr;}
// Usage
Bar* GetBar()
{
ReturnMaybe(GetFoo(), bar)
}
しかし、これはチェーンと冗長性を与えることはできませんが(おそらく、メソッド呼び出しのヌル伝播を除いて)おそらくほぼすべての可能性のうち、上記の解決方法の問題を正確に解決するわけではありません。
編集 - テンプレート化された回答をわずかにに変更しました。
編集2 - 同僚と本の話や他のいくつかのオプションを思い付いた:
#define Maybe(X) (X==nullptr) ? nullptr : X
は使用方法:
return Maybe(foo)->bar;
興味深いことに、これはまた、呼び出しメソッドの場合に動作します。
Maybe(foo)->Bar();
何それが出て展開することは、有効な(奇妙いえ)
(FOO == nullptr)ですので? nullptr:foo-> Bar(); ?あなたは、変数宣言を置くことができないので、
しかし、:速記、あなたは説明ダックをMooingよう
return Maybe(get_next_parent())->child;
から守ることができない、と自分で一時的に作成する必要があります。
オペレータの使用例を教えてください。 –
あなたはハスケルの 'Maybe'モナドのようなものを意味しますか? – kennytm
私はあなたがあなたの「質問」を肉体的にすべきだと思います。おそらくあなたは「はい、彼らが持っている」と探しているだけではありません。あなたのソリューションに関する何かを尋ねたいなら、それを行います(ただし、[codereview.se]もあります)。 –