37
template<typename InputIterator, typename Predicate>
inline InputIterator
find_if(InputIterator first, InputIterator last, Predicate pred, input_iterator_tag)
{
    while (first != last && !bool(pred(*first)))
         ++first;

    return first;
}

I bumped into this snippet in the source code of the implementation of the C++ standard library shipped with GCC 4.7.0. This is the specialization of find_if for an input iterator. I cleaned the leading underscores to make it more readable.

Why did they use a bool cast on the predicate?

qdii
  • 12,505
  • 10
  • 59
  • 116

3 Answers3

31

The reason is that just writing !pred(*first) could result in a call to an overloaded operator! rather than the call to explicit operator bool.

It's interesting that this measure was taken for pred, but an overloaded operator&& can still be selected in the implementation provided. first != last would need to be changed to bool(first != last) to also prevent this overload.

Simple
  • 13,992
  • 2
  • 47
  • 47
12

The standard requires only that the predicate be usable in a context where it can convert to a bool. Presumably, a "predicate" object could have an operator bool function, which did the right thing, and an operator! function which did something totally unrelated. (Of course, that would be horrible design, but the standard requires the library to work as specified, regardless of how bad the user code is.) So g++ converts to bool, and then uses ! on the result of that conversion (where only the build-in operator can apply).

James Kanze
  • 150,581
  • 18
  • 184
  • 329
2

In the C++ Standard there is written relative to the predicate that

In other words, if an algorithm takes Predicate pred as its argument and first as its iterator argument, it should work correctly in the construct pred(*first) contextually converted to bool

The words "contextually converted to bool" means that if even a class defines a conversion function that converts an object of the class to bool as an explicit operator it shall be applied. Consider an example of a contextual conversion to bool

#include <iostream>

struct A
{
   explicit operator bool () const { return true; }
};

int main()
{
   if ( A() ) 
   {
      std::cout << "Here is a contextual conversion to bool" << std::endl;
   }
}

So in context of the C++ Standard quote I do not see any sense in writing expression

first != last && !bool( pred(*first ) )

It would be enough to write

first != last && !pred(*first )

Here pred is contextually converted to bool.

Fred Foo
  • 355,277
  • 75
  • 744
  • 836
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • It is contextually converted to "bool", which is a user defined conversion. But as someone else says in a comment, if there is an `operator!`, it would be preferred. Which seems to be an excellent remark. – Johannes Schaub - litb Feb 17 '14 at 14:35
  • 1
    @Johannes Schaub - litb Then there is a problem. If a class does not define a conversion operator to bool but defines operator ! then the original condition will issue an error. So some realization will be compiled with operator ! while others will not. – Vlad from Moscow Feb 17 '14 at 14:46