破棄をスローする可能性のある値渡し引数による強力な例外安全性保証は可能ですか?


8

スローデストラクタを備えた型と、それを値で受け取る関数があるとします。
その操作は、基本的な例外保証よりも優れたものを提供できますか?
または別の方法で定式化すると、操作にコミットアンドロールバックセマンティクスがあるかどうかを判断するときに、値によって渡された引数の破棄を無視できますか?

#include <cstdlib>

struct X {
    ~X() noexcept(0) {
        if(rand()%6 == 0) throw 0;
    }
    // some state
};

void update(database db, X arg) noexcept;

X x;
update(db, x);

個人的には、ウィキペディアの定義に基づく

  1. 強力な例外安全性コミットまたはロールバックセマンティクスとも呼ばれます:操作は失敗する可能性がありますが、失敗した操作には副作用がないことが保証されているため、すべてのデータは元の値を保持します

関数自体がスローすることさえできないとしてもupdate、強く例外セーフであると説明することは有用ではないと私は思います。

私は私の現在の理解の愚かさを私に示してくれる人、あるいはもっと良い議論をしてくれれば幸いです。


クラスのメソッドがスローし、呼び出し元がオブジェクトを破棄することにした場合はどうなりますか?デストラクタはまだトランザクションを閉じますか?
Robert Harvey、

どのクラスのメソッドですか?そして、どのトランザクションを閉じますか?申し訳ありませんが、私は今混乱しています。
Deduplicator 2015年

まあ、記憶パターンが使われていないか、データベーストランザクションが関係していない限り、オブジェクトが破棄されたときにクラスの状態がどのように失われないかは、ステートレスクラスであると言わない限りわかりません。
Robert Harvey


4
一般に、スローデストラクタは、すべての例外的な安全性保証にとって完全な毒です。それは桁違いに難しくなります。
Sebastian Redl

回答:


7

振り返ってみると本当にわかりませんが、update一般的であるか、X抽象的であるか(例:クローン化および破棄)-つまり、updateについて具体的なことを何も知ることができなかった場合はX、すべての実用的な目的で、強力であると説明します例外安全性保証。少なくとも、これは強力な例外安全性の保証とほぼ同じであり、データ型をX線撮影することなく抽象的なコンテキストを得ることができます。

ただし、X具体的であるため、この質問はかなりあいまいになります。update「強力な例外安全性保証がある」と言うのは、それを強制するためにできることはすべて実行しているので、私は今でも誘惑されます。それはおかしな話のように聞こえますか?それは私には効果的ですが、私は本当にそれをはるかに良くすることはできません。

特に、1人の作成者が実装updateし、もう1人が実装するチーム環境のコンテキストでは、完全にの制御を超えた方法で保証を破る方法で変更できるXため、強力な例外安全性保証を提供できるものはありません。実用的な目的のために、例外パスで独自の副作用をロールバックできる可能性があるすべてのことを実行すると、実際には強力な例外安全性が保証されます。Xupdateupdate

それ以外の場合、強力な例外安全性保証は、非常に多くのシナリオでこれまでに提供することが非現実的なものになります。関数の制御外で状況が変わる可能性があります。物事は、機能の知識を超えた方法で抽象的である可能性があります。どこにでも提供することはほぼ不可能です。その場合、私たちは、強い例外保証が準拠updateする責任を拡大すると言いますか、それとも常にどのように実装されるかを知ることが必要ですか?知りません。これはいずれにしても非常に非現実的であり、私は非現実的ではありません。XupdateX

だから、私はええと、原油で行くつもりです、update例外は安全ですが、X失敗してすべてを台無しにしてしまいました。update's少なくとも問題はありません。アップデートの作者を訴えないでください!作者を訴えXましょう!」Xここでは単にfubarであると説明し、fubarでupdateあるという事実にねじ込まれている強力な例外安全保証を提供する可能性があると説明したいと思いXます。つまり、X'sデストラクタがスローするように設計されているという非常に難しいインターフェースレベルの理解がない限り、私はそれを「大きな問題」として説明する方法がわかりません。これらの保証を付けるには、細かい注意書きと免責事項が必要だと思います。更新は、その強力な例外安全性保証を提供します[...]。そうでない場合、返金はありません!

これは私にとって哲学的な質問のようなもので、考えてみると面白いですが、完全な答えはないかもしれません。とにかく保証とは何ですか?何か保証できますか?ビールを飲むと酔っぱらってしまい、それがいつでも本当のように思えるかもしれませんが、地球外生物が何らかのエイリアンテクノロジーを介入させて使用しているため、どれだけ飲んでも冷静になった場合はどうでしょうか。保証できませこれが起こらないこと。これは非常にありそうもないことであり、そのような出来事が起こった場合、私はそれに無力であると言えるでしょう。私は自分の役割を果たしました。ビールを飲みました。酔うはずです。私はそれを強く保証します。しかし、それは確実ではありません。常にいくつかの可能性がありますが、天文学的には遠く離れていますが、保証が当てはまらない可能性があります。スレッドセーフはどうですか?さて、エイリアンの宇宙船がやって来て、ハードウェアをザップし、メモリ内の命令を再配置して、以前はスレッドセーフであった関数が実行時にスレッドセーフでなくなった場合はどうでしょうか。これが起こらないことは保証できません。しかし、私はエイリアンの宇宙船についてのそのような細かい印刷に行くことなく、スレッドの安全性を保証します。それは人々を気持ちよく、安心させるので、私が言っていることは

デカルトはかつて、「だから私はそう思う」と言った。彼はどうやって知っていますか?そうでない場合はどうなりますか?彼は「ではない」かもしれないが、おそらく「ない」は「考える」ことができる。私が存在するかどうかさえ知りません。とにかく思考はどういう意味ですか?内省的に進んでいるように見え、存在すらしていない私たちが決断をしているように見えるプロセスを説明するために人々が使用する言葉のようなものです。

一部のマシンですべてがビットとバイトである場合はどうなりますか?マトリックスのブロンドまたはブルネットのように。ちなみに、ブロンドや特にブルネットは、このような小さなキャラクターのストリームにどのように保存できますか?彼らはUTF2048のようですか?それは、ある種の異星人のキャラクターの流れでしたが、ユニークなキャラクターがあまり多くないようでした。おそらくそれはある種の関数呼び出しでしょう。とにかく、私たちが何かを保証できるかどうかはわかりません。それはすべて、私たちが真実であると信じていることに関連しています。


5
「したがって、あらゆる種類の「例外安全」と「スローデストラクタ」を同じ文で組み合わせてはなりません。これらは、すべての実用的な目的で、相互に排他的です。」+1、その論理と議論することはできません。できると思うなら、論理的ではありません。

これが元の質問にどのように答えるかはわかりません。ここでの問題は、argが関数の終了時に正確に破壊されることです。関数はこれをキャッチする機会がありません。関数が何かをした場合、それをロールバックする機会はありません。
Nir Friedman、

2
はい、それは正しい結論です。不愉快であることによってそれが正しくなくなることはありません。ベクトルの場合、その含まれている型のデストラクタがこれまでにスローすることは違法です:stackoverflow.com/questions/26902006/…。あなたの「チーム指向」のアプローチは理解できましたが、正直に言うと、それは正確さではなく公平さの観点から見ています。
Nir Friedman、

2
私の好ましい解釈は、デストラクタの投入は未定義の動作であり、関数が持つことを保証する例外はすべて、未定義の動作が発生しないという暗黙の仮定に基づいています(実際、言語のすべてがその仮定を行います)。未定義の動作にハードドライブのフォーマットが含まれる可能性がある場合は、プログラム内の他のすべての例外の保証に違反している可能性があります。
Ixrec

1
@Ixrecそれはあなたの好みの解釈かもしれませんが、デストラクタから投げることは一般的にubではありません、それは単に事実です。
Nir Friedman、2015

-1

技術的に言えば、それはおそらく強力な例外保証を提供することができます。意味のあることに、それが何もしない些細な場合にのみ強力な例外保証を提供することができます。

ハーブサッターは、関数がスローコピーコンストラクターを持つ値によって引数を取る、同様の(そしてより直感的なケース)について話します。このような関数にはnoexceptのラベルを付けることができます。技術的には、例外は、関数自体の内部ではなく、呼び出しコードと呼び出された関数の間の「接着剤」で発生します。ここでもそうです。例外はupdate内で技術的にスローされないため、(おそらく)update自体はエラーを生成せず、したがって強力な例外保証を提供できると主張できます。

実際には、updateが何かを実行する場合、それを呼び出すと(そして何もしない場合)、世界の状態が変化し、例外がスローされ、強力な例外保証が破られる可能性があります。


コメントは詳細な議論のためのものではありません。この会話はチャットに移動しました
maple_shaft
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.