11

The std::basic_string class template has member functions find_first_of and find_first_not_of.

The <algorithm> header, however, contains only a generic find_first_of.

Question1: Is the absence of

std::find_first_not_of(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2)

just an oversight (as for example copy_if) or is it intentionally omitted because the behavior can be achieved with another standard function?

Of course I could write my own find_first_not_of, but

Question2: Is there a ready workaround somewhere in <algorithm>? For example, the absence of copy_if is compensated by the presence of remove_copy_if

Thanks in advance

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • You know better than to write "thanks", Armen! – Lightness Races in Orbit Jul 27 '11 at 14:25
  • @Tomalak: Why does it bother you so much? It's not as if my thanks takes up 50% of my question] – Armen Tsirunyan Jul 27 '11 at 14:26
  • @Tomalak: I've seen your post in meta. I'm not going to roll it back, since you'll call a moderator, but still I am wondering why that bothers you ***so*** much :P – Armen Tsirunyan Jul 27 '11 at 14:28
  • http://meta.stackexchange.com/questions/2950/should-hi-thanks-taglines-and-salutations-be-removed-from-posts/98852#98852 http://meta.stackexchange.com/questions/98149/why-is-it-considered-rude-to-say-thanks-in-advance/98865#98865 – Lightness Races in Orbit Jul 27 '11 at 14:34
  • 1
    I have never thought about it, but this answer clarifies a few things: http://meta.stackexchange.com/questions/98149/why-is-it-considered-rude-to-say-thanks-in-advance/98153#98153 – karlphillip Jul 27 '11 at 19:14

4 Answers4

2

I had this same problem, the short answer to your question: it's not possible with the standard stl libraries (although it is possible with boost::phoenix).

However, you can write your own closure surrounding the sequence iterators that accepts a parameterized 'Value' variable and returns a bool result.

 template<class Iterator> struct is_not_in_range
{
    Iterator const begin;
    Iterator const end;
is_not_in_range(Iterator const& b, Iterator const& e)
    :   begin(b)
    ,   end(e) {}
    template<class Value> bool operator()(Value & v)
    {
          return std::find(begin,end,v) == end;
    }
};

Then you can do this

std::find_if(begin1, end1,  is_not_in_range<Iterator2>(begin2,end2));

Alternatively, you can write a version that uses less branching, but requires a break->continue (approximated with a goto statement)

template<class Iterator1, class Iterator2> Iterator1 find_first_not_of
(   Iterator1 const& begin1
,   Iterator1 const& end1
,   Iterator2 const& begin2
,   Iterator2 const& end2 )
{
    for(Iterator1 mid1 = begin1; mid1 != end1; ++mid1)
    {
        for(Iterator2 mid2 = begin2; mid2 != end2; ++mid2)
            if(*mid1 == *mid2)
                goto FOUND;
        return mid1;
FOUND:      ;
    }
    return end1;
};
Anthony S
  • 21
  • 3
0

There are new functions added in latest STL (Jump to).

all_of, any_of, none_of, find_if_not, copy_if etc.

Ajay
  • 18,086
  • 12
  • 59
  • 105
  • **find_if_not** and **find_first_not_of** are completely different – Armen Tsirunyan Jul 27 '11 at 13:26
  • How would you use **find_if_not** to achieve what **find_first_not_of** is supposed to be for? And also, that is all about C++0x, what about doing it in C++03? – Armen Tsirunyan Jul 27 '11 at 13:29
  • @Ajay: Armen Tsirunyan considered it as a workaround and found yours flawed (reason indicated by his comment). – orlp Jul 27 '11 at 13:29
  • Something like `find_if_not(first1, last1, [=](decltype(*first1) lhs) { return any_of(first2, last2, [=](decltype(*first2) rhs) { return lhs == rhs; })});`? – Steve Jessop Jul 27 '11 at 13:30
  • @Steve: LOL! :) Seriously though, I am asking a C++03 question – Armen Tsirunyan Jul 27 '11 at 13:31
  • 1
    @Armen: OK, then new functions in TR1 are no help even if they did the job. And I think there's a semi-colon missing in my code, should be `});});`! – Steve Jessop Jul 27 '11 at 13:33
  • @Steve: For example which one? – Armen Tsirunyan Jul 27 '11 at 13:37
  • @Armen: I don't mean that those TR1 functions do the job, I mean that even if TR1 contained `find_first_not_of` (which it doesn't), it still wouldn't solve the problem in C++03. If you have to write out the predicate functors then I doubt `find_if_not` `any_of` is any better than `find_if` `find_if`. – Steve Jessop Jul 27 '11 at 13:38
  • @Steve: TR1 can be considered as part of C++03. I mean I am not using a compiler that supports lambdas and such. That's all – Armen Tsirunyan Jul 27 '11 at 13:39
  • "TR1 can be considered as part of C++03" - for the purposes of this question, if you like, but it is not part of the C++03 standard. Are you conflating it with TC1? – Steve Jessop Jul 27 '11 at 13:40
  • @Steve: I agree with you, I mean I know technically TR1 is not part of C++03, but for the purposes of this question let's assume so. No, I am aware of the difference between TR1 and TC1 – Armen Tsirunyan Jul 27 '11 at 13:56
  • @Ajay: You haven't witten anything false in your answer. On the other hand nor have you written anything that has to do anything with my question – Armen Tsirunyan Jul 27 '11 at 18:58
0

I'm not sure about your first question but I think the best you can do is find_if:

template <class Iter>
class Check
{
public:
    Check(Iter first, Iter last) : first_(first), last_(last) { }
    template <class T>
    bool operator()(const T& item) { return std::find(first, last, item) == last; }
private:
    Iter first_;
    Iter last_;
};

find_if(first1, last1, Check<Iter2>(first2, last2));
Mark B
  • 95,107
  • 10
  • 109
  • 188
0

It's easy to write one:

pos = std::find(search_list.begin()...)
if (pos!= npos)
{
   pos = std::find(black_list.begin()...)
   if (pos!= npos)
   {
       continue search
   }
   else
  {
      found !!
  }
}
else
{
   not found
}
cprogrammer
  • 5,503
  • 3
  • 36
  • 56