我注意到我的一些代码中有一个共同的模式
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...
});
这肯定不那么重复,但它仍然有点尴尬。
然而,我真正关心的是对其他人来说是否容易 人们要关注,因为我真的想让我的代码尽可能清晰。
我会用
之类的东西变得更好auto sin = line_reader.get_next_line();
// ...read from sin...
line_reader.check_done(std::move(sin));
答案 0 :(得分:1)
执行setup + cleanup的普通方法是让一个对象的构造函数进行设置,析构函数进行清理(RAII)。
然而,你要做的清理就是在你没有读到最后的时候抛出 - 并且从析构函数中抛出是邪恶的,坏的和错误的。这意味着在这种特殊情况下你不能使用RAII。
如果检查非常重要,那么您拥有的代码将强制执行。如果它只是一个好主意&#34;,那么我认为这两个调用(之前和之后)可能比lambda稍微清晰一些。 (我不会为std::move(sin)
而烦恼 - 使用移动并不会在这里添加任何内容。)