如何报告自定义istream故障



我想使用运算符>>((从控制台读取线性代数数据。我希望操作符>>((的行为与内置数据(如int、double(类似,但我也希望在无法解析输入时报告适当的消息。

我终于构建了一个"custom_stream_failure"类,但总的来说,这相当麻烦。现在我想知道:这是一条路吗,还是存在另一种机制来实现这一目的?这符合标准的精神吗?

我已经包含了一个小的测试程序,它报告"期望"函数中的自定义失败。此外,我还包含了这个问题所涉及的"custom_stream_failure.h"头文件。

#include <iostream>
#include "custom_istream_failure.h"
struct vector_t { int x, y, z; };
bool expect(std::istream& is, char e)
{
if (is.get() != e)
{
custom_istream_failure(is) 
<< "Expected '" << e << ''' 
<< and_throw;
return false;
}
return true;
}
std::istream& operator>>(
std::istream& is, vector_t& v)
{
expect(is, '(') &&
(is >> v.x)     &&
expect(is, ',') &&
(is >> v.y)     &&
expect(is, ',') &&
(is >> v.z)     &&
expect(is, ')');
return is;
}
int main()
{
try
{
std::cin.exceptions(std::istream::failbit);
vector_t vector;
std::cin >> vector;
}
catch (std::exception& e)
{
std::cout << e.what() << std::endl;
}
return 0;
}

#ifndef CUSTOM_ISTREAM_FAILURE
#define CUSTOM_ISTREAM_FAILURE
#include <iostream>
#include <string>
#include <sstream>
class custom_istream_failure
: protected std::stringstream
{
public:
explicit custom_istream_failure(std::istream& is)
: m_is(is)
{}
custom_istream_failure& operator<<(
custom_istream_failure& 
(*pf)(custom_istream_failure&))
{
return ((*pf)(*this));
}
#define CUSTOM_ISTREAM_FAILURE_SOP(D) 
custom_istream_failure& operator<<(D) 
{ 
*static_cast<std::stringstream*>(this) << v; 
return *this; 
}
CUSTOM_ISTREAM_FAILURE_SOP(bool v)
CUSTOM_ISTREAM_FAILURE_SOP(short v)
CUSTOM_ISTREAM_FAILURE_SOP(unsigned short v)
CUSTOM_ISTREAM_FAILURE_SOP(int v)
CUSTOM_ISTREAM_FAILURE_SOP(unsigned int v)
CUSTOM_ISTREAM_FAILURE_SOP(long v)
CUSTOM_ISTREAM_FAILURE_SOP(unsigned long v)
CUSTOM_ISTREAM_FAILURE_SOP(long long v)
CUSTOM_ISTREAM_FAILURE_SOP(unsigned long long v)
CUSTOM_ISTREAM_FAILURE_SOP(float v)
CUSTOM_ISTREAM_FAILURE_SOP(double v)
CUSTOM_ISTREAM_FAILURE_SOP(long double v)
CUSTOM_ISTREAM_FAILURE_SOP(void* v)
CUSTOM_ISTREAM_FAILURE_SOP(std::streambuf* v)
CUSTOM_ISTREAM_FAILURE_SOP(
std::ostream& (*v)(std::ostream&))
CUSTOM_ISTREAM_FAILURE_SOP(
std::ios& (*v)(std::ios&))
CUSTOM_ISTREAM_FAILURE_SOP(
std::ios_base& (*v)(std::ios_base&))
CUSTOM_ISTREAM_FAILURE_SOP(char v)
CUSTOM_ISTREAM_FAILURE_SOP(signed char v)
CUSTOM_ISTREAM_FAILURE_SOP(unsigned char v)
CUSTOM_ISTREAM_FAILURE_SOP(const char* v)
CUSTOM_ISTREAM_FAILURE_SOP(const signed char* v)
CUSTOM_ISTREAM_FAILURE_SOP(const unsigned char*v);
#undef CUSTOM_ISTREAM_FAILURE_SOP
private:
std::istream& m_is;
friend custom_istream_failure& and_throw(
custom_istream_failure&);
};
inline custom_istream_failure& and_throw(
custom_istream_failure& cif)
{
try { throw std::ios_base::failure(cif.str()); }
catch (...)
{ 
cif.m_is.setstate(std::ios::failbit, true);
}
return (cif);
}
#endif // CUSTOM_ISTREAM_FAILURE

一种方法是让类型的输入运算符处理错误条件(下面的示例(。如果用户希望在出现错误时抛出异常,setstate将触发适当的异常。对于不希望出现异常的用户,只需以通常的方式检查输入流的状态即可。

std::istream &operator>>(std::istream &is, vector_t &v) {
char c;
if (is >> c && c == '(') {
int x = 0;
if (is >> x >> c && c == ',') {
int y = 0;
if (is >> y >> c && c == ',') {
int z = 0;
if (is >> z >> c && c == ')') {
v = {x, y, z};
return is;
}
}
}
}
is.setstate(std::ios_base::failbit);
return is;
}

最新更新