Generally I certainly agree with Lionel and you. But it's not
always that easy. Sometimes you don't have control over the
naming, and even if you have, often the return value only
indicates success or failure of a larger procedure with lots
of side effects, say,
if( GenerateRevenueReports() )
...
I wouldn't want to change that name into something more "boolean", say,
if( GenerateRevenueReportsWasSuccessful() )
...
It's not clear now if the function actually performs the
action or only queries for its status. So, even with all the
arguments, I still understand why some people might find
if( GenerateRevenueReports() == true )
...
It doesn't say anything more than just:
if ( GenerateRevenueReports() ) ...
I think it was Herb Sutter who first brought up the issue, but
there's already a serious problem if a function named
GenerateRevenueReports() returns a bool to indicate success: is
it true, the function succeeded, or true, there was an error?
The correct way to handle this is with an enum:
enum Result { success, failure } ;
Result GenerateRevenueReports() ;
In which case, of course, you write:
if ( GenerateRevenueReports() == success )
...
My general rule is that function names are verbs or verbal
clauses, and that predicate functions always use a form of the
verb to be or to have, e.g.: isRunning(), hasNoProblems(). Any
other function will use an enum (or some other user defined
type---I rather like a user defined type which asserts in its
destructor if it hasn't been tested) to report success or
failure.
There are exceptions, of course. The iostream idiom is too
ubiquious to be ignored, for example (and you can't change the
standard library even where it is completely irrational). And
there are cases where it makes sense to treat an extended type
as a bool, or verbs other than to be or to have which logically
respond with a bool (e.g. RegularExpression::matches()).