web-dev-qa-db-ja.com

tryブロックから参照を取得する

C++を使用して、次のように何かを実行したいと思います。

  1. たとえば、マップ内の何かへの参照を取得してみてください
  2. 投げたらすぐに戻る
  3. それ以外の場合は、参照してください

ただし、C++で初期化しないと参照オブジェクトを宣言できないため、これを直接行うことはできません。

たとえば、値を渡して良ければ、次のようにできます。

std::map<char, int> mymap {...};
int x;
try {
    x = m.at('a');
} catch (out_of_range& e) {
    return;
}
// do something with x

ただし、参照が必要なため、コンパイルされない次のことを行う必要があります。

std::map<char, int> mymap {...};
int& x;
try {
    x = m.at('a');
} catch (out_of_range& e) {
    return;
}
// do something with x

したがって、私が見ることができるオプションは、(1)回避したいポインタを使用する、または(2)別のマップメソッドを使用して、より詳細なコードを生成します。

std::map<char, int> mymap {...};
auto x_it = m.find('a');
if (x_it == m.end()) {
    return;
}
int& x = x_it->second;
// do something with x

それらが唯一の選択肢ですか、またはこれをきちんと行う別の方法はありますか?

6
Alex

通常の方法は、tryブロック内でも「xで何か」の行を移動することです。

std::map<char, int> mymap {...};
try {
    int& x = mymap.at('a');
    // do something with x
} catch (out_of_range& e) {
    return;
}

例外のいいところは、例外がスローされると、throwとcatchの位置の間のすべてのコードが完全にスキップされることです。
つまり、try { ... } catchその行に到達すると、すべてが正常に機能しているという知識でブロックします。

bothtryおよびcatchブランチから参照を返したい場合は、次のように簡単です。

std::map<char, int> mymap {...};
int &x = [&]() -> int & { try {
    return mymap.at('a');
} catch (std::out_of_range& e) {
    return some_default_value;
} } ();
// do something with x

しかし、あなたの場合、tryブランチのみが参照を返すため、tryブロック全体の戻り値の型はint &ではなく、optional<int &>に似ています。問題は、C++ 17がまだリリースされていないことです。

それにもかかわらず、optional<int &>int *に同型であるため、最終的にここでポインタを使用することは正しいことのように思われます。 ->構文が気に入らない場合は、int &y = *x;を再割り当てするだけです。

1
Rufflewind