6
struct CCompare
{
    const bool operator()(const int& lhs, const int& rhs) const {
        return lhs < rhs;
    }
};

Warning 1 warning C4180: qualifier applied to function type has no meaning;

I saw the usage with return value as const bool in a programming book. When I compiled the above code with vs2010, it reports the warning C4180.

The following code instead will not cause the same warning.

struct CCompare
{
    bool operator()(const int& lhs, const int& rhs) const {
        return lhs < rhs;
    }
};

Question1> Is it true that the usage of const Fundamental_Data_Types as a function returned value doesn't make sense?

Question2> Is it true that the usage of const Type as a function returned value only makes sense iff the Type is a class/struct?

Thank you

// Update //

struct CClass
{
    int val;
    CClass(int _val) : val(_val) {}

    void SetValue(int _val) {
        val = _val;
    }
};

struct CCompare
{
    const CClass getMe() const {
        return CClass(10);
    }

    CClass getMeB() const {
        return CClass(10);
    }
};

int main(/*int argc, char *argv[]*/) 
{
    CCompare c;

    c.getMe().SetValue(20);   // error
    c.getMeB().SetValue(20);  // ok
}
q0987
  • 31,246
  • 61
  • 222
  • 356
  • 4
    In both cases, the return value is copied to the caller. You have no right to enforce `const` on a copied value they're getting back. – chris Jul 08 '13 at 14:32
  • 4
    `const` only makes sense if you return a reference or a pointer, regardless of whether it is a class/struct or fundamental type. – Roger Rowland Jul 08 '13 at 14:33
  • @RogerRowland Refer to Effective C++ 3rd pp 18 `const Rational operator*(const Rational&, const Rational&);` – q0987 Jul 08 '13 at 14:42
  • @q0987 Ok, but my copy is at home, so it will have to wait unless you can explain? – Roger Rowland Jul 08 '13 at 14:45
  • @RogerRowland That's not correct. Think about calling a member function on the return value, e.g. `func1().func2()`. If `func1` returns a const, then you can only call `func2` if it is const. – James Kanze Jul 08 '13 at 14:48
  • @JamesKanze so how does that make what I said wrong? Can you give another example? If I understand your comment, you mean calling a function on a returned temporary? – Roger Rowland Jul 08 '13 at 14:54
  • @RogerRowland, here is what Scott Meyers has to say. The `const` in front of `Rational` helps make the following code invalid. `Rational a, b, c; (a*b) = c;` and `if (a*b = c) // oops, meant to do a comparison` – q0987 Jul 08 '13 at 15:15
  • @q0987 ah, ok, I've got it now - thanks for pointing that out, I should have thought more carefully (I've read those books so many times too!) ... FWIW, I don't get that warning on VS2012 even at max warning level. – Roger Rowland Jul 08 '13 at 15:19
  • @RogerRowland, That book just likes a bible and you can appreciate more when you read more:) – q0987 Jul 08 '13 at 15:20
  • @q0987 lol - it's much more effective learning to get publicly corrected on SO ;-) – Roger Rowland Jul 08 '13 at 15:21
  • @q0987, That advice has been deprecated. The proper way to prevent that would be to make `operator=` only take lvalues, which you can do with rvalue references for `this`. – chris Jul 08 '13 at 15:37
  • @chris The only way to ensure that a function only takes lvalues as it's left operand is to make it a free function, taking a non-const reference, e.g. `MyClass& operator+=( MyClass& lhs, MyClass const& rhs )`. And `operator=` can't be a free function. – James Kanze Jul 08 '13 at 15:59
  • @JamesKanze, Shouldn't `MyClass &operator=(MyClass rhs) &;` do it? – chris Jul 08 '13 at 16:08
  • @chris `MyClass& operator=( MyClass const& rhs );` won't compile unless it is a member, and if it is a member, there's no requirement that the left operand be an lvalue; you can call member functions on rvalues. – James Kanze Jul 08 '13 at 16:12
  • @JamesKanze, But you can specify `this` to be an lvalue with the [C++11 feature](http://stackoverflow.com/questions/8610571/what-is-rvalue-reference-for-this), which is now starting to be supported among compilers. – chris Jul 08 '13 at 16:13

1 Answers1

7

Yes and yes to both of your questions. Return values are rvalues, and cv-qualifiers only apply to rvalues if they have a class type.

The reason for this is fairly simple: there's normally nothing you can do with an rvalue where const-ness would make a difference—it's a value, after all, and not an object. With a class type, there are member functions to take into account (which means that you can get an lvalue from the rvalue), so const-ness suddenly becomes relevant.

James Kanze
  • 142,482
  • 15
  • 169
  • 310
  • Can you detail why cv-qualifiers only apply to rvalues? `const int leftValue = 10`. Here the `const` is applied to a lvalue. I assume that I misunderstood your point. – q0987 Jul 08 '13 at 15:18
  • @q0987 You're misreading me. `const` can apply to all lvalues. It can only apply to rvalues if they have class type. – James Kanze Jul 08 '13 at 16:00