Reputation: 37914
In C conditional-oriented operators evaluate to either 1
or 0
of type int
(even if it does have dedicated _Bool
type). Referring to C11 N1570 draft:
C11 §6.5.8/6 Relational operators
Each of the operators
<
(less than),>
(greater than),<=
(less than or equal to), and>=
(greater than or equal to) shall yield 1 if the specified relation is true and 0 if it is false.107) The result has typeint
.C11 §6.5.9/3 Equality operators
The
==
(equal to) and!=
(not equal to) operators are analogous to the relational operators except for their lower precedence.108) Each of the operators yields 1 if the specified relation is true and 0 if it is false. The result has typeint
. For any pair of operands, exactly one of the relations is true.C11 6.5.13/3 Logical AND operator
The
&&
operator shall yield 1 if both of its operands compare unequal to 0; otherwise, it yields 0. The result has typeint
.C11 6.5.14/3 Logical OR operator
The
||
operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it yields 0. The result has typeint
.
As I checked C++ seems to be different in this matter, as in following example (see 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;
}
outputs b
, which as I guess indicates bool
type. Does C++ guarantee that all of these operators always evaluate to bool
type (in contrast to C)?
Upvotes: 14
Views: 1096
Reputation: 145829
Contrary to C, in C++, relational operators, equality operators and logical operators (logical AND, logical OR and logical negation) all yield a value of type bool
.
For example:
(C++11, 5.9p1 Relational operators) "[...] The type of the result is bool."
EDIT: for the sake of completeness, all the operators listed above can be overloaded and thus the resulting type can be changed. See Arne Vogel answer for real life example.
Upvotes: 12
Reputation: 6666
No, because of operator overloading. This has been mentioned before, but I can give the real life example of expression templates. The idea, generally, is to allow writing "lazy" expressions (that is, really, function objects or ASTs) with syntax that is very similar to the normal, eager use of logical operators. Typically, many other operators, in particular arithmetic operators are also, overloaded.
For instance, one design goal of Boost.Lambda was to simplify the use of algorithms:
std::string str;
// ...
std:.string::iterator firstA = std::find_if(str.begin(), str.end(), _1 == 'a' || _1 == 'A');
Previously, in "pure" C++98, it was generally necessary to write numerous named functions or function objects before many standard algorithms could be used effectively.
Since C++11, Boost.Lambda is not as useful any more since lambda expressions have been added to the core language. There are still numerous EDSLs (embedded domain-specific languages) where C++11 lambdas cannot replace expression templates though, e.g. you may want to generate SQL command strings directly from a C++ EDSL in a way similar to LINQ in .NET, but as a portable library solution. Another example: the VexCL library uses expression templates to generate GPU kernels.
This is probably the only legitimate use of non-bool return types for overloaded logical operators, but it's not generally considered esoteric.
Upvotes: 14