Подтвердить что ты не робот

Почему этот бросок нужен?

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;
}

Я столкнулся с этим фрагментом в исходном коде реализации стандартной библиотеки С++, поставляемой с GCC 4.7.0. Это специализация find_if для входного итератора. Я очистил ведущие символы подчеркивания, чтобы сделать его более читаемым.

Почему они использовали приведение bool к предикату?

4b9b3361

Ответ 1

Причина в том, что просто запись !pred(*first) может привести к вызову перегруженного operator!, а не к вызову explicit operator bool.

Интересно, что эта мера принималась за pred, но перегруженный operator&& может быть выбран в предоставленной реализации. first != last необходимо будет изменить на bool(first != last), чтобы предотвратить эту перегрузку.

Ответ 2

Стандарт требует только того, чтобы предикат можно было использовать в контекст, где он может конвертироваться в bool. Предположительно, объект "предикат" может иметь функцию operator bool который сделал правильную вещь, и функцию operator!, которая что-то совершенно не связанное. (Конечно, это было бы ужасно дизайн, но стандарт требует, чтобы библиотека работала как указанному, независимо от того, насколько плохим является код пользователя.) Так что g++ преобразуется в bool, а затем использует ! в результате этого преобразование (где может применяться только оператор сборки).

Ответ 3

В стандарте С++ написано относительно предиката, что

Иными словами, если алгоритм принимает Predicate pred в качестве аргумента и сначала как аргумент итератора, он должен корректно работать в create pred (* first), контекстно преобразованный в bool

Слова "контекстно преобразованные в bool" означают, что если даже класс определяет функцию преобразования, которая преобразует объект класса в bool как явный оператор, он применяется. Рассмотрим пример контекстного преобразования в 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;
   }
}

Итак, в контексте стандартной цитаты С++ я не вижу смысла в написании выражения

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

Достаточно написать

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

Здесь pred преобразуется в контекст в bool.