streambuf または Basic_ostringstream を派生していますか?
-
20-09-2019 - |
質問
文字列ストリームを派生させて、operator<< を使用してスローされるメッセージを構築できるようにしたいと考えています。API は次のようになります。
error("some text") << " more text " << 42 << std::endl;
これにより、次のことが行われるはずです
throw "some text more text 42"
そこで私がしたのは、「overflow」メソッドをオーバーロードするerrorbuf(streambufから継承)を作成してから、ostream(&errorbuf)を作成することです。代わりにbasic_ostringstreamか何かを継承する必要はないのかな...
解決
私は再びここに私のお気に入りのマクロを小走ります:
#define ATHROW( msg ) \
{ \
std::ostringstream os; \
os << msg; \
throw ALib::Exception( os.str(), __LINE__, __FILE__ ); \
} \
の使用においてます:
ATHROW( "Invalid value: " << x << " should be " << 42 );
例外のタイプは自分のライブラリからですが、私はあなたのアイデアを得ると思います。これは、独自のストリームクラスを派生よりもはるかに簡単で、かつ<<()OPと厄介な合併症の多くを回避できます。
他のヒント
あなたはおそらくのようなものをすることによって、それが簡単に作ることができます:
class error_builder
{
public:
error_builder(const std::string& pMsg = "")
{
mMsg << pMsg;
}
~error_builder(void)
{
throw std::runtime_error(mMsg.str());
}
template <typename T>
error_builder& operator<<(const T& pX)
{
mMsg << pX;
return *this;
}
private:
std::stringstream mMsg;
};
error_builder("some text") << " more text " << 42 << std::endl;
ので、私はstd::runtime_error
を使用し、あなたがしているようにあなたが文字列を投げるべきではないことに注意してください。すべての例外はstd::exception
は、そのようにすべての意味の例外がconstのruntime_error
でキャッチすることができないstd::exception&
、から派生する必要があります。
これは完全な表現の終わりまでの一時的な生活のために動作します。
一部の事業者はGManのソリューションから欠落してます。
class error {
public:
explicit error(const std::string& m = "") :
msg(m, std::ios_base::out | std::ios_base::ate)
{}
~error() {
if(!std::uncaught_exception()) {
throw std::runtime_error(msg.str());
}
}
template<typename T>
error& operator<<(const T& t) {
msg << t;
return *this;
}
error& operator<<(std::ostream& (*t)(std::ostream&)) {
msg << t;
return *this;
}
error& operator<<(std::ios& (*t)(std::ios&)) {
msg << t;
return *this;
}
error& operator<<(std::ios_base& (*t)(std::ios_base&)) {
msg << t;
return *this;
}
private:
std::ostringstream msg;
};
私は通常、独自の例外クラスを作成するだけです。オーバーライドするだけで済みます what()
コンストラクターは好きなだけ提供できます。エラー メッセージを作成するには、上記のように vasprintf (利用可能な場合) または std::ostringstream を使用するだけです。
以下に例を示します。
class CustomException : public std::exception {
private:
const std::string message;
public:
CustomException(const std::string &format, ...) {
va_list args;
va_start(args, format);
char *formatted = 0;
int len = vasprintf(&formatted, format.c_str(), args);
if (len != -1) {
message = std::string(formatted);
free(formatted);
} else {
message = format;
}
va_end(args);
}
const char *what() const {
return message.c_str();
}
};
vasprintf がない場合は、スタック上のバッファを使用して vsnprintf を使用することもできます。