C++ 標準では:
system_category
現在のC++17 ドラフトでは、次のように述べられています。
C++ 標準ライブラリの特定の関数は、std::error_code
(19.5.2.1) オブジェクトを介してエラーを報告します。そのオブジェクトのcategory()
メンバーはstd::system_category()
、オペレーティング システムに起因するエラーに対して返される
か、他の場所に起因するエラーに対して実装定義error_category
オブジェクトへの参照を返します。実装では、これらの各エラー > カテゴリに対して value() の可能な値を定義する必要があります。[例: POSIX に基づくオペレーティング システムの場合、実装では、オペレーティング システムのドキュメントで定義されている追加の値を使用して、std::system_category()
値を POSIX 値と同一として定義することが推奨されます。errno
POSIX に基づいていないオペレーティング システムの実装では、オペレーティング システムの値と同じ値を定義することが推奨されます。オペレーティング システムに起因しないエラーの場合、実装によって、関連する値の列挙型が提供される場合があります。
あまり明確ではありません:
generic_category
これは、POSIX エラー コードを で使用できることを意味しますgeneric_category
。非 POSIX 値は、 で正しく機能しない可能性がありますgeneric_catgeory
。実際には、私が使用してきた実装によってサポートされているようです。
ブーストで
ブーストシステム自体
Boost のドキュメントは、この機能について非常に簡潔です。
元の提案では、エラー カテゴリを errno (つまり POSIX スタイル) とネイティブ オペレーティング システムのエラー コードとの間のバイナリ選択と見なしていました。
さらに、次のようなレガシー宣言を見つけることができます。
static const error_category & errno_ecat = generic_category();
でlinux_error.hpp
:
API エラーの後に error_code を作成するには:error_code( errno, system_category() )
でwindows_error.hpp
:
API エラーの後に error_code を作成するには:error_code( ::GetLastError(), system_category() )
でcygwin_error.hpp
:
API エラーの後に error_code を作成するには: error_code( errno, system_category() )
Windows の場合、Boost はエラーsystem_category
以外に使用します。errno
ec = error_code( ERROR_ACCESS_DENIED, system_category() );
ec = error_code( ERROR_ALREADY_EXISTS, system_category() );
ec = error_code( ERROR_BAD_UNIT, system_category() );
ec = error_code( ERROR_WRITE_PROTECT, system_category() );
ec = error_code( WSAEWOULDBLOCK, system_category() );
ASIOでは
ASIO には、次のようなコードがあります。
template <typename ReturnType>
inline ReturnType error_wrapper(ReturnType return_value,
boost::system::error_code& ec)
{
#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
ec = boost::system::error_code(WSAGetLastError(),
boost::asio::error::get_system_category());
#else
ec = boost::system::error_code(errno,
boost::asio::error::get_system_category());
#endif
return return_value;
}
POSIXコードのerrno
ように見つけます:system_category
int error = ::pthread_cond_init(&cond_, 0);
boost::system::error_code ec(error,
boost::asio::error::get_system_category());
ファイルシステム
POSIXコードでerrno
見つけます:generic_category
if (::chmod(p.c_str(), mode_cast(prms)))
{
if (ec == 0)
BOOST_FILESYSTEM_THROW(filesystem_error(
"boost::filesystem::permissions", p,
error_code(errno, system::generic_category())));
else
ec->assign(errno, system::generic_category());
}
GNU libstdc++ では
ファイルシステム
errno
で見つけますgeneric_category
:
if (char* rp = ::realpath(pa.c_str(), buf.get())) {
[...]
}
if (errno != ENAMETOOLONG) {
ec.assign(errno, std::generic_category());
return result;
}
の使用はありませんsystem_category
。
libstdc++ の使用
実際には、 libstdc++を使用generic_category
して非 POSIXに使用できるようです。errno
std::error_code a(EADV, std::generic_category());
std::error_code b(EADV, std::system_category());
std::cerr << a.message() << '\n';
std::cerr << b.message() << '\n';
与えます:
Advertise error
Advertise error
Libc++
errno
で見つけますsystem_category
:
int ec = pthread_join(__t_, 0);
if (ec)
throw system_error(error_code(ec, system_category()), "thread::join failed");
の使用はありませんgeneric_category
。
結論
ここでは一貫したパターンは見つかりませんが、どうやら:
system_category
WindowsでWindowsエラーを使用するときに使用することが期待されています。
generic_category
の POSIX 値に安全に使用できますerrno
。
std::generic_category
の非POSIX値には使用できないはずですerrno
(機能しない可能性があります)。
errno
値が POSIXかどうかを確認したくない場合:system_error
POSIXベースのシステムで使用できることが期待されていますerrno
(厳密に言えば、これのサポートは義務付けられておらず、推奨されているだけです)。 POSIX ベースのシステムではsystem_error
、errno
.
新しい提案 (更新 2019-12)
新しいエラー システムを導入する提案があります ( std::error
、std::status_code
)。
施設の問題に関する議論については、関連する議論とそのセクション 4 を参照してください。<system_error>
- std::string の使用
- 「2 API」ライブラリの急増
- 0 列挙子を無視する文言はありません
- シングルトンへの依存
- error_category サブクラスをリテラル型にすることはできません
- error_code に追加情報を添付するためのガイダンスはありません
- operator== の驚くべきオーバーロードへの依存
- error_category は適切に error_domain という名前にする必要があります
- 標準の error_code-yielding 関数はとにかく例外をスローできます
- 指定されていない error_code 比較セマンティクス