我会立即为这么模糊的名字道歉,我不知道如何概括地描述这个任务。
假设我们有一个类可以做一些工作:
class Worker{
public:
bool doWork(int arg);
};
如果作业成功完成,该方法doWork
将返回。true
现有员工之一必须完成这项工作。为此,我想使用std::find_if
struct DoWork{
int arg;
explicit DoWork(int arg):
arg(arg)
{}
bool operator()(Worker &worker) const{
return worker.doWork(arg);
}
};
std::vector<Worker> workers;
//...
std::find_if(workers.begin(), workers.end(), DoWork(42));
这个想法是这样的。该算法将遍历工人,直到有人完成工作或他们用完为止。但我被模糊的怀疑所折磨,是否有可能这样做。这里有未定义的行为吗?这段代码在不同的 stl 实现上总是工作相同吗?
下面明确定义了一元函数谓词std::find、std::find_if、std::find_if_not:
1) 函数必须为所需元素返回 true
2)函数原型应该类似于入口:
const 可以省略,但函数在任何情况下都不得修改通过传递的对象可用的数据。
3) 类型必须使迭代器可以取消引用并隐式转换为类型。
这是为什么?符合 C++11 的编译器允许由编译器本身组织的并行化和优化。如果谓词可以改变值的值会怎样?这可能会导致谓词的另一次传递给出不同的结果,即不明确的结果。一个集合可以是这样的,改变另一个成员应该导致顺序的改变,这在通过引用传递对象的值时是不可能的,也就是说,理论上迭代器应该改变——是改变后第一个遇到的元素(并且它在正确的地方)结果是未知的。
find_if 的行为应该类似于以下实现。
不要混淆:这绝不是强制实施。函数可以通过编译器的静态分析器以特殊方式处理,将其变成最适合特定情况的代码。谓词参数通过迭代器解引用传递,它假定使用解引用的常量版本。
我没有看到任何未定义的行为 - 只要您传递正确的开始和结束迭代器,以及具有正确行为的谓词。
只要 STL 实现符合标准,代码就可以工作。
“我认为是”(c)维尼
对传递的谓词的要求
std::find_if
指定谓词参数不必是常量引用,但无论如何,禁止谓词修改传递给它的对象。对于算法,
std::find_if
只是没有给出这样的许可(不像,比如说, fromstd::for_each
)。我不会随便说修改操作是如何形式化定义的,但是如果你的函数DoWork
修改了容器的元素,那么有可能形式上是不可能这样做的。另外更远的地方
参数
std::find_if
只是Predicate pred
,即 这部分已经明确禁止你的选择,如果它DoWork
是Worker
. 同样,这个定义中有漏洞,但我认为这个想法很清楚。当然,如果实施不是专门为恶意破坏和抓捕标准违规者而设计的,那么很难想象这里会出现什么问题……