Why does the standard library have find and find_if?

前提是你 提交于 2019-12-01 15:32:17

A predicate is a valid thing to find, so you could arrive at ambiguities.


Consider find_if is renamed find, then you have:

template <typename InputIterator, typename T>
InputIterator find(InputIterator first, InputIterator last, const T& value);

template <typename InputIterator, typename Predicate>
InputIterator find(InputIterator first, InputIterator last, Predicate pred);

What shall be done, then, with:

find(c.begin(), c.end(), x); // am I finding x, or using x to find?

Rather than try to come up with some convoluted solution to differentiate based on x (which can't always be done*), it's easier just to separate them.

*This would be ambiguous, no matter what your scheme is or how powerful it might be†:

struct foo
{
    template <typename T>
    bool operator()(const T&);
};

bool operator==(const foo&, const foo&);

std::vector<foo> v = /* ... */;
foo f = /* ... */; 

// f can be used both as a value and as a predicate
find(v.begin(), v.end(), f); 

†Save mind reading.

T.E.D.

Here's what Stroustrup said (The C++ Programming Language, 18.5.2):

If find() and find_if() had the same name, surprising abmiguities would have resulted. In general, the _if suffix is used to indicate that an algrithm takes a predicate.

As to what exactly that "ambiguity" is, Steve Jessop answered that in his (top rated) answer to this SO question.

(note: that question may actually qualify as the same question as this one. I'm not quite smart enough in C++ arcania to decide).

It can't have the same name because there would be an ambiguity. Suppose that we had a find overload instead of find_if. Then suppose:

// Pseudo-code
struct finder
{
    bool operator()(const T&) const { ... }
    bool operator==(const finder& right) const { ... }
}

std::vector<finder> finders;

finder my_finder;

std::find(finders.begin(), finders.end(), my_finder);

The find would have no way to resolve the inconsistency: Should it attempt to find the finder in the container, or use the finder to do the find operation? To solve this problem they created two function names.

You can certainly implement find in terms of find_if using some sort of equality predicate.

I would guess that the real reason is that you can implement find fairly easily and provide performant specialised implementations for typical encountered types; if you are using find_if, the predicate you pass in can be arbitrarily complex, which gives the library implementer less scope of optimisation.

Also, C++ has the philosphy of "you don't pay for what you don't use" and you'd normally expect that you don't want to pay for a predicate evaluation if a simple comparison will do.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!