3

boost ::optionalオブジェクトの値を取得しようとすると、BOOST_ASSERTを使用して、オブジェクトが実際に初期化されていることを確認します。

しかし、初期化されていないオプションを逆参照するときに私が望むのは、例外がスローされることです-リリースビルドでこの動作を取得する方法はありますか?そうでない場合、この動作をする他の同様のライブラリはありますか?

オブジェクトを逆参照する前に毎回is_initializedメソッドを使用するのは嫌です。また、この動作を実現するために、オプションのクラスを自分のクラスでラップすることは避けたいと思います。

4

2 に答える 2

3

残念ながら、オプションではそのようなオプションは提供されません。オプションの要点は、オーバーロードされたブール演算子を使用して、値が存在するかどうかを確認できるようにすることです。

オプションは、関数で例外をスローしないように設計されていますが、代わりに値を使用して成功/失敗を返します。

代わりに常に値を返し、失敗した場合は関数内にスローする必要がありますか?

于 2010-01-27T10:54:02.220 に答える
3

から例外を定義boost::assertion_failed(...)BOOST_ENABLE_ASSERT_HANDLERてスローすることができますboost::optional

コード:

#include<boost/exception/to_string.hpp>

namespace boost{
void assertion_failed(char const* expr, char const* function, char const* file, long line){
    throw std::runtime_error(std::string()
        + expr + 
        " from " + function +
        " at " + file + ":" + boost::to_string(line)
    );
}
}

#define BOOST_ENABLE_ASSERT_HANDLER
#include <boost/optional.hpp>
#undef BOOST_ENABLE_ASSERT_HANDLER

int main(){
    double d = *boost::optional<double>{}; // throws! (width fairly useful msg)
    (void)d;
}

エラーメッセージ(例外がキャッチされない場合)は次のようになります。

terminate called after throwing an instance of 'std::runtime_error'
  what():  this->is_initialized() from reference_type boost::optional<double>::get() [T = double] at /usr/include/boost/optional/optional.hpp:992

その他のリファレンス: http: //boost.2283326.n4.nabble.com/optional-How-to-make-boost-optional-throw-if-trying-to-access-uninitialized-value-td2591333.html

ノート:

assertion_failed1)一般的に役立つには、のきめ細かい定義が必要になる場合があります。別の種類の例外をスローしたい場合は、関数に条件を設定する以外の方法はわかりませんassertion_failed(これも私の好みにはハックすぎます):

namespace boost{
void assertion_failed(char const* expr, char const* function, char const* file, long line){
    if(std::string("this->is_initialized()") == expr) throw std::domain_error("optional is not intialized");
    throw std::runtime_error(std::string()
        + expr + 
        " from " + function +
        " at " + file + ":" + boost::to_string(line)
    );
}
}

2)私は他の答えに同意しません、私は1つが行動を選ぶことができるべきだと思います。そして、立ち往生することassertは良い選択肢ではありません。私の意見では、boost::optional関数の戻りを含まないコンテキストでの使用があります。

3)std::experimental::optionalバージョンがあります。不思議なことに、彼らは値をとるときにこの問題にとらわれないことに決めました*チェックされていない値が返されるため、これは生のポインターの非動作と一致します)が、メンバーは例外.value()をスローできます。std::experimental::bad_optional_accessこれは興味深い設計上の選択です(さらに、2つの方法assertのいずれも正しいとは思いません)。

于 2015-07-04T08:20:31.230 に答える