エラー処理のためにから継承されたクラスを使用しており、が呼び出されたstd::system_error
ときに何が返されるかを制御したいと考えています。what()
理由: 標準 (C++11 とドラフト C++1y CD - N3690 の両方、§ 以下の参照は後者です) は、によって返される文字列がどのwhat()
ように見えるかを正確に指定していません。 .6.2 (14):
注: 返された NTBS は、
what_arg + ": " + code.message()
. — エンドノート
したがって、実装依存と見なされます。(ちなみに、code().message()
代わりにすべきではありませんcode.message()
か?)
what()
したがって、問題は次のとおりです。標準に準拠し、実装に依存したくない場合 (つまり、移植可能にしたい場合) に返される文字列を正確に定義するにはどうすればよいでしょうか?
コードを好む人のために:
class my_class : public std::system_error {
public:
my_class(std::error_code ec, std::string const & what_arg)
: system_error(ec, /* this string is not required to be equal to what is returned by what() */)
{
// ok, try it here
// but what is the name of the member storing the string?
}
const char * what() const noexcept
{
// ok, try it here
// but how to access what_arg in its unaltered form?
}
};
わかりました、私が好きではない簡単な解決策は次のとおりです。
class my_class : public std::system_error {
std::string my_what;
public:
my_class(std::error_code ec, std::string const & what_arg)
: system_error(ec, what_arg),
my_what( /* construct my what string */ )
{ }
const char * what() const noexcept
{ return my_what.c_str(); }
};
仮想なのでstd::exception::what()
機能しますが、実装の詳細を使用せずにもっとエレガントな方法はありますか? 2 つの文字列を格納するという考えは好きではありませstd::system_error
んmy_what
。
問題の根源: std::runtime_error — たまたま std::system_error の親クラス — には、コンストラクターの事後条件である §1.9.2.6 (3) に正確な要件があります。
strcmp(what(), what_arg.c_str()) == 0
の場合はstd::system_error
、§19.5.6.2 (2) で次のようになります。
string(what()).find(what_arg) != string::npos
code().message()
標準が に含めようとするのがなぜそんなに難しいのか、誰にも手がかりがありますwhat()
か? code()
はエラー コード オブジェクトを返すので、誰でもcode().message()
いつでも (このクラスの例外がキャッチされたときでも) 文字列に含めることができます。
の要件が の要件とstd::system_error
同じである場合、次のstd::runtime_error
ように書くことができます。
class my_class : public std::system_error {
public:
my_class(std::error_code ec, std::string const & what_arg)
: system_error(ec, /* build my what string here */ )
{ }
};
エレガントでポータブルなソリューションはありますか?
更新: 以下のコメントの多くは、エラー メッセージが実装定義であると述べています。によって返される文字列をフォーマットしたいだけでwhat()
、すべてのシステムでバイトごとに同等にしたくないことを理解しています。ログに記録するか、サードパーティに渡したいと考えてみてください。一定の形式に従う必要があります(これは標準で提案されているものではありません)。
UPDATE2: std::system_error は OS または STL エラーだけではないと思います。そこから独自のクラスを派生させて、エラー報告に使用することができます (そしてそうすると思います)。低レベルの API を書いている場合はどうなりますか? ところで、高レベル API での使用が禁止されているのはなぜですか?
API のエラー処理部分ですべての引数をコンストラクターに渡すと、実装で定義された (つまり不明な) エラー文字列は含まれませんが、データを複製せずにフォーマットすることはできません。