Pergunta

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?

Foi útil?

Solução

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.

Outras dicas

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).

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top