gpt4 book ai didi

c++ - 如何在 C++ 中创建事务流?

转载 作者:行者123 更新时间:2023-11-30 03:01:07 29 4
gpt4 key购买 nike

我需要在 C++ 中创建“事务流”。我所说的“事务流”是指如果在处理过程中的某个时刻出现错误,将会倒带的流。例如,如果流的使用者因某种原因无法处理流的数据,我希望流恢复到生成该数据之前的状态。

也许惰性流可以实现这一点?这是具有通用解决方案的常见情况,还是我必须为我的特定问题编写自己的自定义实现?

最佳答案

嗯,首先想到的是将范围接口(interface)(用于惰性和可组合性)与事务接口(interface)(用于回溯)结合起来:

#include <iostream>
#include <stack>
#include <sstream>

struct transaction_failure {};

class transactional_istream_range {

std::istream& stream;
std::stack<std::streampos> states;

public:

transactional_istream_range(std::istream& stream)
: stream(stream) {}

// Transaction interface.

template<class R, class T>
R transaction(R(*body)(T&)) {
try {
begin();
R result = body(*this);
commit();
return result;
} catch (const transaction_failure&) {
rollback();
}
return R();
}

void begin() {
states.push(stream.tellg());
}

void commit() {
states.pop();
}

void rollback() {
stream.seekg(states.top());
states.pop();
}

// Range interface.

bool empty() const {
return stream.peek() == EOF && stream.eof();
}

char front() const {
return stream.peek();
}

void pop_front() const {
stream.ignore(1);
}

};

然后您可以轻松编写在事务范围上运行的模板函数:

#include <cctype>

template<class R>
std::string parse_integer(R& input) {
std::string result;
while (!input.empty()) {
if (std::isdigit(input.front())) {
result += input.front();
input.pop_front();
} else {
throw transaction_failure();
}
}
return result;
}

int main() {
std::istringstream stream("1234a");
typedef transactional_istream_range tir;
tir input(stream);
std::string result = input.transaction(parse_integer<tir>);
std::cout << "Result: " << result;
}

这只是初步估计;您可能不必指定事务函数的范围类型(​​即,仅 parse_integer 而不是 parse_integer<...> )。以范围形式编写多种惰性流和惰性算法非常简单。

至于对此进行扩展,您可以参数化事务处理以调用用户指定的提交或回滚函数,或者单独实现每种类型的回滚。使用 mixin 将范围接口(interface)与事务接口(interface)分离也可能是有益的。不过,我现在想不出一个不求助于虚函数的好方法。

关于c++ - 如何在 C++ 中创建事务流?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11453654/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com