はじめに
C++で、ファイルが存在しない、ネットワークがダウンしている、アクセス権がない、といったOSが原因のエラーを処理する場合、単なる int
のエラーコードを返すだけでは、エラーの原因が何であるかが分かりにくくなります。
C++11では、このようなプラットフォーム依存のエラーを、移植性の高い、統一的な方法で扱うための仕組みとして、<system_error>
ヘッダーが導入されました。
std::error_code
: エラーコードの値とそのカテゴリ(どの種類のエラーか)をペアで保持する。std::system_error
:error_code
をラップする例外クラス。
この記事では、これらのクラスを使って、OSレベルのエラーを型安全にハンドリングする方法を解説します。
【前提】C++11とは?
C++11は、2011年に正式化されたC++言語のメジャーアップデート版です。<system_error>
ライブラリはこのC++11で導入されたため、利用するにはC++11以降に対応したコンパイラが必要です。
error_code
/ system_error
を使ったサンプルコード
このコードは、データベースへの接続をシミュレートする関数を定義します。接続に失敗した場合、エラーの種類に応じて error_code
を設定し、system_error
例外をスローします。
完成コード
#include <iostream>
#include <system_error> // error_code, system_error
#include <string>
using namespace std;
// データベース接続をシミュレートする関数
void connect_to_database(bool should_fail) {
if (should_fail) {
// 1. errc列挙体から、エラーコードを作成
error_code ec = make_error_code(errc::connection_refused);
// 2. error_codeをラップしたsystem_error例外をスロー
throw system_error(ec, "データベースに接続できませんでした。");
} else {
cout << "データベースへの接続に成功しました。" << endl;
}
}
int main() {
// 3. system_error例外をcatchする
try {
connect_to_database(true); // 失敗するケース
}
catch (const system_error& e) {
// 4. エラー情報を取得
const error_code& ec = e.code();
cout << "エラーが発生しました。" << endl;
cout << " 詳細: " << e.what() << endl;
cout << " カテゴリ: " << ec.category().name() << endl;
cout << " エラー値: " << ec.value() << endl;
cout << " メッセージ: " << ec.message() << endl;
}
return 0;
}
コードの解説
1. std::error_code
error_code
は、エラーコードの値(int
)と、その値がどのような種類のエラーなのかを示すカテゴリ(error_category
へのポインタ)をペアで保持します。
error_code ec = make_error_code(errc::connection_refused);
std::errc
:<system_error>
で定義されている、移植性の高い標準的なエラー条件を表す列挙型です。errc::network_down
(ネットワークダウン)やerrc::permission_denied
(アクセス権なし)などがあります。make_error_code()
:errc
の列挙子から、対応するerror_code
オブジェクトを簡単に作成するためのヘルパー関数です。
2. std::system_error
system_error
は、std::exception
から派生した例外クラスです。 throw system_error(ec, "追加メッセージ");
- 第1引数: エラーの原因を示す
error_code
オブジェクト。 - 第2引数(オプション): エラーに関する、より具体的な文脈を示す文字列。
3. try-catch
ブロック
main
関数では、system_error
例外を catch
しています。これにより、OSレベルのエラーが発生してもプログラムがクラッシュせず、エラー情報を分析して適切な対応をとることができます。
4. エラー情報の取得
catch
ブロックで捕捉したsystem_error
オブジェクト e
から、様々な情報を取得できます。
e.code()
: 元となったerror_code
オブジェクトを返します。e.what()
:system_error
のコンストラクタで渡された追加メッセージと、error_code
のメッセージを組み合わせた、詳細なエラー説明文字列を返します。ec.message()
:error_code
に対応する、プラットフォーム標準のエラーメッセージ(例:"Connection refused"
)を返します。
まとめ
今回は、C++11の <system_error>
ライブラリを使って、OSレベルのエラーを扱うための標準的な方法を解説しました。
std::errc
: 移植性の高い、共通のエラー条件を表す列挙型。std::error_code
: エラーコードの値とカテゴリを保持する。std::system_error
:error_code
をラップする例外クラス。
この仕組みを使うことで、ファイル操作やネットワーク通信などで発生しうる様々なプラットフォーム依存のエラーを、統一的で型安全な方法でハンドリングすることができます。