cpprefjpでfuture関係を書いてるのでその検証。
たとえば、std::promiseに対して2回以上値を書き込むと、std::future_error例外が投げられます。
#include <iostream> #include <future> #include <thread> #include <functional> void foo(std::promise<int>& p) { p.set_value(3); try { p.set_value(1); } catch (std::future_error& e) { std::cout << e.code().message() << std::endl; } } int main() { std::promise<int> p; std::future<int> f = p.get_future(); std::thread t(foo, std::ref(p)); std::cout << f.get() << std::endl; t.join(); }
3 Promise already satisfied
std::future_errorクラスはstd::logic_errorを継承した例外クラスですが、std::system_errorと同じようにstd::error_codeを扱います。
namespace std { class future_error : public logic_error { public: future_error(error_code ec); const error_code& code() const noexcept; const char* what() const noexcept; }; }
std::future_errorのエラー値はstd::future_errcというenum classです。
namespace std { enum class future_errc { broken_promise, future_already_retrieved, promise_already_satisfied, no_state }; }
これをstd::error_codeで扱うために、std::future_category()関数が用意されています。
namespace std { const error_category& future_category() noexcept; }
この関数で返されるstd::error_categoryオブジェクトが、std::future_errcのエラー値に対応するエラーメッセージを管理します。
std::error_codeには、std::future_errcの値とstd::future_category()をセットで渡して使います(自分で使うことはないはず)。
#include <iostream> #include <future> int main() { std::error_code ec = { static_cast<int>(std::future_errc::promise_already_satisfied), std::future_category() }; std::cout << ec.message() << std::endl; }
Promise already satisfied
毎回std::future_category()を設定しなくていいように、std::make_error_code()関数にstd::future_errcのためのオーバーロードが用意されています。
namespace std {
error_code make_error_code(future_errc e) noexcept;
}
#include <iostream> #include <future> int main() { std::error_code ec = std::make_error_code(std::future_errc::promise_already_satisfied); std::cout << ec.message() << std::endl; }
Promise already satisfied
以上です。
std::error_codeで自分用のエラー情報を扱う場合のいい拡張例ですね。