我最近看了 Sean Parent 在 2013 年关于 C++ seasoning 的演讲。如果我没有理解错的话,他说你可以从你的代码中消除几乎所有(所有?)手写循环。我的问题是如何实现这一目标? 让我们考虑以下代码:
class ProgressDialog
{
//interesting part of that class
void SetPosition(int position);
bool IsCancelRequested();
void SetHeader(const std::string& status);
}
void foo( const std::vector<std::string>& v)
{
ProgressDialog dlg;
long position = 0;
for( const auto& s : v)
{
++position;
dlg.SetPosition(position);
dlg.SetHeader("Processing"+ s);
DoSomethingThatTakesSomeTime(s);
if(dlg.IsCancelRequested()) break;
}
}
有没有办法重构手写循环?
最佳答案
我不确定这是否会增加任何清晰度,但这是重构循环和提前中断概念的尝试。
#include <string>
#include <vector>
#include <ciso646>
struct ProgressDialog
{
//interesting part of that class
void SetPosition(int position);
bool IsCancelRequested();
void SetHeader(const std::string& status);
};
void DoSomethingThatTakesSomeTime(std::string const&);
// iterate over a container, calling func with the current value.
// if func returns false, cease iterating immediately.
// return true if terminated early
// note: func must return false if it wishes early termination,
// otherwise true
template<class Cont, class F>
auto for_each_while(Cont&& container, F&& func)
{
for(auto&& s : container)
if (not func(s))
return true;
return false;
}
void foo( const std::vector<std::string>& v)
{
auto update_dialog =
[position = 0, dlg = ProgressDialog()](auto&& s) mutable
{
++position;
dlg.SetPosition(position);
dlg.SetHeader("Processing"+ s);
DoSomethingThatTakesSomeTime(s);
return !dlg.IsCancelRequested();
};
for_each_while(v, update_dialog);
}
这里有一些 std 库滥用实现了同样的目的。
我强烈建议您不要这样做,因为一般读者并不清楚发生了什么!
void foo( const std::vector<std::string>& v)
{
int position = 0;
auto dlg = ProgressDialog();
std::find_if(begin(v), end(v),
[&](auto&& s)
{
++position;
dlg.SetPosition(position);
dlg.SetHeader("Processing"+ s);
DoSomethingThatTakesSomeTime(s);
return dlg.IsCancelRequested();
});
}
关于c++ - 将手写循环转换为标准库调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52603405/