【发布时间】:2018-05-04 19:56:29
【问题描述】:
偶尔在测试代码中我想设置/模拟一些全局变量,在测试/范围结束时我想恢复这些变量。例如:
BOOST_AUTO_TEST_CASE(HttpClientCsrf)
{
std::string csrfSave = Http::getCsrfToken();
... some test code
Http::setCsrfToken(csrfSave); // restore csrf
}
这里明显的问题是,如果some test code 在到达终点之前返回(或抛出),您将无法恢复该csrfSave 变量。所以,简单的改进是编写一些简单的结构包装器,在 dtor 中自动恢复值:
struct CsrfSave
{
std::string csrfSave;
CsrfSave()
{
csrfSave = Http::getCsrfToken();
}
~CsrfSave()
{
Http::setCsrfToken(csrfSave);
}
};
BOOST_AUTO_TEST_CASE(HttpClientCsrf)
{
CsrfSave csrfSave;
... some test code
// dtor of CsrfSave restores csrf
}
这总体上解决了问题,但是,对于每个函数,您需要编写大量样板代码。所以,问题是:什么是最短和最简单的方法可以用来实现相同的目标,同时最小化并可能避免所有样板文件。
我使用的一种这样的方法,我对此不太满意:
BOOST_AUTO_TEST_CASE(HttpClientCsrf)
{
std::string csrfSave = RBX::Http::getLastCsrfToken();
shared_ptr<void> csrfSaveScope(NULL, [&](void*) {
RBX::Http::setLastCsrfToken(csrfSave);
});
... some test code
}
还有什么更好的吗?我宁愿避免编写任何实用程序类,并且宁愿避免提升(除非它包含在下一个标准中)。 这种模式经常发生在不同的项目中(不共享代码),每次我最终编写简单的结构包装器或使用 lambda 的通用包装器时,我都希望看到其他可以就地编码的方法就像我在 shared_ptr exmpale 中展示的那样
【问题讨论】:
-
您可以自己制作一个通用范围保护并将一个函数传递给它的构造函数。类似this question.
-
当然 - unique_ptr。为什么需要 shared_ptr?带有自定义删除器的 unique_ptr 应该可以解决问题
-
@SeverinPappadeux is not unique_ptr 使用删除器作为模板参数?它会无缝地工作吗?
-
是的,你需要模板参数。代码
auto main() -> int { int ttt = 77; auto deleter = [&](void*) { std::cout << "Deleter called\n"; std::cout << ttt << "\n"; // do something with capture here instead of print }; std::unique_ptr<void, decltype(deleter)> p((void*)1, deleter); std::cout << "done\n"; return 0; } -
@SeverinPappadeux 与我的 shared_ptr 示例相比显然太混乱了
标签: c++