Являются ли условные выражения в С++ всегда типа bool?

В C условно-ориентированные операторы оценивают либо 1, либо 0 типа int (даже если он имеет выделенный тип _Bool). Ссылаясь на проект C11 N1570:

C11 §6.5.8/6 Реляционные операторы

Каждый из операторов < (меньше), > (больше), <= (меньше или равно), а >= (больше или равно) должно давать 1, если указанное отношение истинно и 0, если оно ложно. 107) Результат имеет тип int.

C11 §6.5.9/3 Операторы равенства

Операторы == (равно) и != (не равные) аналогичны реляционные операторы, за исключением их более низкого приоритета. 108) Каждый из операторы дают 1, если указанное отношение истинно и 0, если оно false. Результат имеет тип int. Для любой пары операндов точно верно одно из соотношений.

C11 6.5.13/3 Логический оператор И

Оператор && должен давать 1, если оба его операнда сравнивают неравные до 0; в противном случае он дает 0. Результат имеет тип int.

C11 6.5.14/3 Логический оператор OR

Оператор || должен давать 1, если один из его операндов сравнивается не равный 0; в противном случае он дает 0. Результат имеет тип int.

Как я заметил, С++ кажется другим в этом вопросе, как в следующем примере (см. http://ideone.com/u3NxfW):

#include <iostream>
#include <typeinfo>

int main() {
    double x = 10.0;

    std::cout << typeid(x <= 10.0).name() << std::endl;

    return 0;
}

выводит b, который, как я думаю, указывает тип bool. С++ гарантирует, что все эти операторы всегда оценивают тип bool (в отличие от C)?

Ответы

Ответ 1

В отличие от C, в С++ реляционные операторы, операторы равенства и логические операторы (логическое И, логическое ИЛИ и логическое отрицание) дают значение типа bool.

Например:

(С++ 11, 5.9p1 Relational operator) "[...] Тип результата - bool."

EDIT: для полноты, все перечисленные выше операторы могут быть перегружены и, следовательно, результирующий тип может быть изменен. См. Ответ Арне Фогеля для реальной жизни пример.

Ответ 2

Нет, из-за перегрузки оператора. Это уже упоминалось ранее, но я могу привести пример реальной жизни шаблонов выражений. Идея, как правило, заключается в том, чтобы разрешить писать "ленивые" выражения (то есть, действительно, функциональные объекты или AST s) с синтаксисом, который очень похож на нормальный, нетерпеливый использование логических операторов. Как правило, многие другие операторы, в частности арифметические операторы, также перегружены.

Например, одной целью проекта Boost.Lambda было упростить использование алгоритмов:

std::string str;
// ...
std:.string::iterator firstA = std::find_if(str.begin(), str.end(), _1 == 'a' || _1 == 'A');

Ранее, в "чистом" С++ 98, обычно было необходимо написать многочисленные именованные функции или функциональные объекты, прежде чем можно будет эффективно использовать многие стандартные алгоритмы.

Так как С++ 11, Boost.Lambda уже не так полезен, поскольку на основной язык добавлены лямбда-выражения. Есть еще множество EDSL (встроенных доменных языков), где С++ 11 lambdas не могут заменить шаблоны выражений, например, вы можете генерировать строки команд SQL непосредственно из С++ EDSL способом, подобным LINQ в .NET, но как решение для переносимых библиотек. Другой пример: библиотека VexCL использует шаблоны выражений для генерации ядер GPU.

Это, пожалуй, единственное законное использование возвращаемых типов non-bool для перегруженных логических операторов, но оно обычно не считается эзотерическим.