views:

839

answers:

10

Which is better:

bool MyClass::someQuery() const;

const bool MyClass::someQuery() const;

I've been using 'const bool' since I'm sure I remember hearing it's "what the ints do" (for e.g. comparison operators) but I can't find evidence of that anywhere, mostly due to it being difficult to Google and Intellisense not helping out any ;) Can anyone confirm that?

To me returning const values (this isn't just about bools) makes more sense; it'll prevent temporaries being modified, which is almost always going to be a programmer mistake. I just want something to back that up so I can extol returning const values to my colleagues :)

+11  A: 

When you returning a refernce to a member variable it makes sense to make it const. Here you are returning a copy, hence there is no need of const.

Naveen
+2  A: 

It completely doesn't matter. Therefore, the consensus is to return just bool.

The reason that it doesn't matter is that you can't call non-const member functions anyway; bool is not a class or struct.

MSalters
+11  A: 

So you know it's right, you're just after the Voice of Authority? Preventing accidental modification of temporaries is very valuable. In general, you should declare as many things as you possibly can const, it protects you from a variety of accidents and gives the optimiser useful hints.

D'you have a copy of Scott Meyers' "Effective C++" around? Point them at Item 3 (page 18 in the third edition) ;)

It gives the example of

class Rational {...};
const Rational operator* (const Rational& lhs, const Rational& rhs );

if( (a * b) = c ) // declaring operator *'s return value const causes error to be caught by compiler
moonshadow
No idea why this was getting voted down, it's exactly the answer I was looking for! Thanks :)Not that I'm putting down any other answers of course; I did also ask "which is better" so opinions on added complexity and so on are also welcome.
Ben Hymers
This has nothing to do with his question. He hasked about whether it made sense to make a *bool* return value const. And you answer with a complex non-POD type. -1
jalf
@Ben: It was voted down because it has nothing to do with your question. For a bool, or other built-in types, returning const makes zero difference, and this example wouldn't have compiled anyway.
jalf
Actually I did say "this isn't just about bools", and it's only his example that mentions non-bools anyway. Perhaps I should change the title to "Should I return a value or const value?" - is it ok to change titles of questions here or would that just annoy everyone?
Ben Hymers
@Ben: Your "(this isn't just about bools)" has probably escaped many readers while the caption "bool or const bool?" caught everybody's eyes. FWIW, I have tried to answer your question taking your small comment into account.
sbi
And "values" could be considered as referring to bools, floats, doubles - i.e. instances of types that are "less OO".
MSalters
In response to the other points about "it doesn't matter for bool". It is beginning to be popular to refer to fundamental types via typedefs. The logic being that it's easier to port code that refers to "int32_t" than code referring to "int". There's no reason that for some of those types they'll be implemented as UDTs anyway! Adding 'const' ensures consistent behaviour.
Richard Corden
I'd be very surprised if an `int32_t` wasn't a POD. That would, for example, prevent it from being used in a `union`. That's not something one would expect.
sbi
@sbi: The union example is a red herring, if you're using unions then you're already at such a low level in the code that abstractions are no longer an option. On a 64 bit architecture there may not actually be a 32 bit fundamental type, and so 'int32_t' could be a UDT. The bigger picture is that you might have "Width", "Height" etc which may or may not be UDTs.
Richard Corden
+1  A: 

const return type

SUMMARY:

The value of a return type that is declared const cannot be changed. This is especially usefull when giving a reference to a class’s internals, but can also prevent rarer errors.

adatapost
+15  A: 

This is the case when const adds no value but inflates the code and makes the reader think more. What's the point of this const? The caller can copy the value into some non-const variable and do whatever he wants with it anyway.

sharptooth
+3  A: 

The const modifier is only used for return types that are returned by reference (either as reference const SomeObject& or via a pointer const SomeObject*), so the caller won't be able to modify the object via the reference/pointer. Primitive types are returned by value, which means that the caller receives a copy of the the object, not the object itself.

Therefore, const is not really appropriate for returned value types. Since the copy is outside of the control of the called function, the called function should not dictate to the caller that it cannot be changed.

Jen
+7  A: 

Note that if((a*b) = c) won't compile for built-in types anyway, so it is very relevant here whether we're talking built-in types (your question asks for bool) or user-defined types.

For built-in types it makes no sense at all, so it shouldn't be used. And for user-defined types, I'm in jalf's camp: What if the caller wants to modify the returned object?

I'm not convinced that if((a*b) = c) is such a good argument for returning const user-defined types, since I can't remember the last time I've seen a compiler not warn about this.

sbi
Ok, but it fails for other reasons. The normalise(crossProduct(a,b)) example is probably better there, though the example I whipped up on codepad fails because I'm guessing it's based on gcc, which disallows binding of temporaries to non-const references... in MSVC it should succeed, against the programmer's intention.
Ben Hymers
@Ben: MS calls the ability of their compiler to bind temporaries to non-const references a "feature", bit it is, in fact, a bug.
sbi
See my comment on the question about the normalise(...) "example".I even didn't mention the MS "it's not a bug, it's a feature" thingy about binding rvalues to non-const references!
rstevens
PODs include simple structs like `struct A { int a, b; };`, which will work fine with `(a*b) = c`. But i've heard for C++0x they talk about making the `operator=` only work for lvalues, making this code snippet invalid. I wish that they would do that, but probably they would break too much code :(
Johannes Schaub - litb
@litb: Dammit, I thought I was on the safe side with PODs! I'll replace them with "built-in types".
sbi
A: 
const bool func();
bool f = func();

0 errors, 0 warnings. What have you accomplished other than unnecessary code inflation?

Chris Becke
That's ok though; the copy is explicit, and any modifications are going to be explicit. It doesn't achieve anything in that circumstance; it's more to prevent accidental modification of temporaries, where modification will be lost at the end of the statement.
Ben Hymers
+1  A: 

As bool is going to be copied, it's the same, to put const or not. Plus you'll may have some compil problems.

+5  A: 

To be a little more specific, only "objects" can be const. The C++ standard's definition of "object" includes everything an lvalue refers to ("has a name") and class-type temporaries. A boolean return value is an rvalue of a non-class type which is why a standards-compliant compiler will just ignore "const" in this case. As others said already, it's useless in this context.

sellibitze
Thanks for the extra detail! Does this mean though that it *would* be useful for class types?
Ben Hymers
Yes. Some people prefer to return const objects to prevent assignments. This is usually motivated by a possible typo if (get_object() = blah) ...which won't compile if the function get_object() returns a const object (of some class-type). But I never considered this to be a big problem. In the light of C++0x, rvalue references and move semantics returning const objects can be counterproductive and decrease performance. C++0x offers a better solution for preventing assignments on rvalue objects: ref qualifiers.
sellibitze
Excellent answer. I wish I could vote this up twice.
Ben Hymers