views:

3084

answers:

4

When I compiled my C++ code with GCC 4.3 for the first time, (after having compiled it successfully with no warnings on 4.1, 4.0, 3.4 with the -Wall -Wextra options) I suddenly got a bunch of errors of the form warning: type qualifiers ignored on function return type.

Consider temp.cpp:

class Something
{
public:
    const int getConstThing() const {
        return _cMyInt;
    }
    const int getNonconstThing() const {
        return _myInt;
    }

    const int& getConstReference() const {
        return _myInt;
    }
    int& getNonconstReference() {
        return _myInt;
    }

    void setInt(const int newValue) {
        _myInt = newValue;
    }

    Something() : _cMyInt( 3 ) {
        _myInt = 2;
    }
private:
    const int _cMyInt;
    int _myInt;
};

Running g++ temp.cpp -Wextra -c -o blah.o:

temp.cpp:4: warning: type qualifiers ignored on function return type
temp.cpp:7: warning: type qualifiers ignored on function return type

Can someone tell me what I am doing wrong that violates the C++ standard? I suppose that when returning by value, the leading const is superfluous, but I'm having trouble understanding why it's necessary to generate a warning with it. Are there other places where I should leave off the const?

+15  A: 

It doesn't violate the standard. That's why they're warnings and not errors.

And indeed you're right — the leading const is superfluous. The compiler warns you because you've added code that in other circumstances might mean something, but in this circumstance means nothing, and it wants to make sure you won't be disappointed later when your return values turn out to be modifiable after all.

Rob Kennedy
That it warns and not errors does not mean anything. Other invalid code like `sizeof(void)` also does merely warn, but is clearly forbidden. The Standard does not know the difference between warnings and errors: Both are diagnostics.
Johannes Schaub - litb
@litb: What he said is still correct. Of course the fact that they're warnings doesn't *guarantee* that it won't violate the standard as you say, but the *reason* they're made warnings instead of errors is that the compiler implementers did not want to prohibit it. And the reason they didn't want to prohibit it is because it does not violate the standard.
jalf
Does it violate the standard at all?
Philipp
I think my first sentence was rather clear on that, @Philipp. Look at the question Johannes mentioned in the question comment: [Why is a type qualifier on a return type meaningless?](http://stackoverflow.com/questions/1607188/why-is-type-qualifier-on-return-type-is-meaningless)
Rob Kennedy
+4  A: 

I encountered this warning when compiling some code that uses Boost.ProgramOptions. I use -Werror so the warning was killing my build, but because the source of the warning was in the depths of Boost I couldn't get rid of it by modifying my code.

After much digging I found the compiler option that disables the warning:

-Wno-ignored-qualifiers

Hope this helps.

I had the same problem, and ended up setting Boost's include path with `-isystem` instead of `-I`, which suppresses all warnings raised by Boost headers.
Philipp
A: 

Scott Meyers pointed out that there's pretty good reason why someone would want to return const values. Here's an example:

int some_calculation(int a, int b) { int res = 0; /* ... */ return res; }

/* Test if the result of the calculation equals 40.*/
if (some_calculation(3,20) = 40)
{

}

Do you see what I did wrong? This code is absolutely correct and should compile. The problem is that the compiler didn't understand that you intended to*compare instead of assign* the value 40.

With a const return value the above example won't compile. Well, at least if the compiler doesn't discard the const keyword.

No, it shouldn't compile. The result of `some_calculation` is an rvalue of type int. You can't assign to rvalues of non-class type.
Charles Bailey
And if the return value is of class type, the `const` is correct and doesn't generate a warning.
Philipp
A: 

Having this

struct Foo { Foo(int) {} operator bool() { return true; } };

and that

Foo some_calculation(int a, int b) { Foo result(a + b); /*...*/ return result; }

the example

if (some_calculation(3, 20) = 40) { /*...*/ }

compiles without a warning. Of course, this is rare. But isn't const correctness about making it hard for people to do things wrong? And with the expectation that people try things, that are wrong, the return type should be declared const. And: g++ warns about ignoring the classifier, but does not ignore it. I think, the warning is about users that take the copy and ignore the const classifiers on their copy. But that should not be a warning, because this is absolutely correct behavior. And it makes sense to do this.

mcbulba
G++ wouldn't warn here if you added a `const`. The `const` qualifier is only ignored for non-class type return values.
Philipp