Являются ли условные выражения в С++ всегда типа 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 для перегруженных логических операторов, но оно обычно не считается эзотерическим.