Я заметил общий шаблон в моем коде
std::string line;
if (!in || !std::getline(in, line)) {
throw line_read_error(in,line_counter);
}
++line_counter;
std::istringstream sin{line};
// ...read from sin...
if (!sin.eof()) {
sin.clear();
throw incomplete_read_error(in,line_counter,sin.tellg());j
}
То, что я читал из строки, было различным в каждом месте, но настройки и проверка после чтения были идентичны.
Я учел это, создав объект для хранения моего in
потока и line_counter
, и передав обратный вызов для тела:
class LineReader {
std::istream& in;
size_t line_counter;
public:
template <typename Function>
void with_next_line(Function callback) {
std::string line;
if (!in || !std::getline(in, line)) {
throw line_read_error(in,line_counter);
}
++line_counter;
std::istringstream sin{line};
callback(sin);
if (!sin.eof()) {
sin.clear();
throw incomplete_read_error(in,line_counter,sin.tellg());j
}
}
// ...
}
Изменив мои использования на
line_reader.with_next_line([/*...*/](auto& sin){
// ...read from sin...
});
Это, конечно, меньше повторений, но все же немного неловко.
Однако меня действительно беспокоит то, будет ли другим людям легко следовать, как я на самом деле пытаюсьсделать мой код как можно более разборчивым