1. ホーム
  2. c++

[解決済み] std::optionalはどのように使うべきですか?

2022-03-05 23:27:53

質問

のドキュメントを読んでいます。 std::experimental::optional が何をするものなのかがよくわからないのです。 いつ どう使えばいいのか、どう使えばいいのか。このサイトにはまだ例が載っていないので、このオブジェクトの本当のコンセプトを把握するのが難しいのです。というのは std::optional を使うのが良い選択なのか、以前の標準(C++11)になかったものをどのように補っているのか。

どのように解決するのか?

最もシンプルな例を挙げます。

std::optional<int> try_parse_int(std::string s)
{
    //try to parse an int from the given string,
    //and return "nothing" if you fail
}

同じことを参照引数で実現することもできますが(次のシグネチャのように)、その場合は std::optional を使うと、シグネチャと使い方がすっきりします。

bool try_parse_int(std::string s, int& i);

もう一つの方法として 特に悪い :

int* try_parse_int(std::string s); //return nullptr if fail

この場合、動的なメモリ割り当てや所有権の心配などが必要になります。- 常に上記の他の2つのシグネチャのいずれかを選択します。


別の例

class Contact
{
    std::optional<std::string> home_phone;
    std::optional<std::string> work_phone;
    std::optional<std::string> mobile_phone;
};

のようなものを持つよりも、非常に好ましい。 std::unique_ptr<std::string> を各電話番号に割り当てることができます。 std::optional を使えば、データの局所性を確保でき、パフォーマンスも向上します。


もう一つの例。

template<typename Key, typename Value>
class Lookup
{
    std::optional<Value> get(Key key);
};

もしルックアップに特定のキーがなければ、単純に "値なし." を返せばいいのです。

こんな風に使えるんだ。

Lookup<std::string, std::string> location_lookup;
std::string location = location_lookup.get("waldo").value_or("unknown");


別の例

std::vector<std::pair<std::string, double>> search(
    std::string query,
    std::optional<int> max_count,
    std::optional<double> min_match_score);

のすべての可能な組み合わせを取る4つの関数のオーバーロードを持つよりも、ずっと理にかなっています。 max_count (ない場合もある)と min_match_score (または、そうでない)!

また 排除する 呪われた パス -1 のために max_count 制限を設けない場合"または"Pass std::numeric_limits<double>::min() に対して min_match_score 最低点数を求めないのであれば"!


別の例

std::optional<int> find_in_string(std::string s, std::string query);

クエリ文字列が s が必要です。 int -- ない この目的のために誰かが決めた特別な値 (-1?) 。


その他の例として boost::optional ドキュメント . boost::optionalstd::optional は、動作や使い方が基本的に同じになります。