2017-03-10 10 views
1

のは、我々はいくつかのタイプT用タイプstd::optional<T>の変数std :: optional w/oの中にインスタンスを置くことは可能ですか?

std::optional<T> x; 

があるとしましょう。 xの内部にTのコンストラクタを呼び出して初期化する場合は、メンバ関数std::optional::emplaceを呼び出すことができます。私が知っているように、このメンバ関数は、インスタンスがすでに存在するかどうかをチェックします(つまり、がtrueと評価されます)。そうである場合、先に構築されたインスタンスを破棄し、提供されたコンストラクタおよび引数を使用して、

このチェックと破棄を行わずに初期化しかできないのだろうかと思います。 std::optionalを扱うときは、インスタンスが存在するかどうか最初に確認し、その結果に応じて別の作業を行うのが一般的です。したがって、std::optionalのインスタンスを入れ替える必要があるときは、初期化されたインスタンスが含まれていないことが既に分かっています。したがって、std::optional::emplaceの「安全でないバージョン」を提供することは妥当と思われますが、std::optionalにはそのようなメンバー機能はありません。これを達成する方法はありますか?おそらく、

は、(私はないと思います)std::optionalためのメモリレイアウトに関するいくつかの保証がある場合は、その後、私は直接配置newオペレーターを呼び出すことができます...

+0

私はまともな最適化コンパイラがこれらの無駄なチェックを削除できることを願っています。このチェックが最適化された後もチェックされていますか? – JVApen

+0

@JVApen特に、コンパイルがインライン化に失敗した別の関数の内部で構築が行われているときは、そうはしませんが、常にそうとは限りません。 –

+0

すでに空であるアサーションを追加しようとしましたか?もちろん、@JVApen – JVApen

答えて

2

いいえ、それは不可能です。そして、いいえ、optionalが従事していることを示すoptionalにフラグを設定しなければならないので、メモリに直接配置newを呼び出すことは役に立たないでしょう。それを外部で行うことはできません。我々はstd::optional内のインスタンスを据え付けるする必要がある場合に

したがって、我々はすでに、それは強力な引数ではありません任意の初期化インスタンス

が含まれていないことを知って、かなり頻繁にそれを主張するのが妥当と思われます。 emplace()は、単にoperator=の上の潜在的な最適化であり、optionalの現在の状態に関するこのような関数の使用に暗黙のヒントはありません。あなたのコードが同じように構成されている場合

また、:

if (!o) { 
    // stuff 
    o.emplace(some, args, here); 
} 

あなたのコンパイラがexplicit operator bool()チェックと内部emplace()チェック間の重複の分岐を参照し、それらを一緒に崩壊し、そうなることを安心することができないだろう余分な枝である。

+0

"メモリレイアウトに関する保証"とは、フラグ変数の位置に保証を含めることを意味していました。そして、私は、通常のものと一緒に「思いついた」バージョンの「emplace」を提供しない理由はないと思う。 'unsafe_emplace'のような名前は、プログラマーがそれを過度に使うのを妨げるかもしれないと私は思います。コンパイラが最大の最適化フラグにもかかわらず、 'std :: optional :: emplace'をインライン化できなかったので、アセンブリが生成されたことを確認して、二重チェックが行われました。 –

関連する問題