Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't the compiler smarter in this const function overloading problem?

The following code does not compile:

#include <iostream>
class Foo {
  std::string s;
 public:
  const std::string& GetString() const { return s; }
  std::string* GetString() { return &s; }
};

int main(int argc, char** argv){
  Foo foo;
  const std::string& s = foo.GetString(); // error
  return 0;
}

I get the following error:

const1.cc:11: error: 
invalid initialization of reference of type 'const std::string&' 
from expression of type 'std::string*

It does make some sense because foo is not of type const Foo, but just Foo, so the compiler wants to use the non-const function. But still, why can't it recognize that I want to call the const GetString function, by looking at the (type of) variable I assign it to? I found this kind of surprising.

like image 679
Frank Avatar asked Dec 09 '22 16:12

Frank


2 Answers

The return type is determined from the overloaded function which is actually called, it never forms a part of overload resolution itself. (What if the return type wasn't used?)

const isn't the problem with the return value as you can bind a non-const object to a const reference, it's the fact that your function is returning a pointer which you don't dereference.

As foo is not const, the non-const GetString() is called - it is a better match for a non-const object. You need:

const std::string& s = *foo.GetString();
like image 167
CB Bailey Avatar answered Jan 17 '23 05:01

CB Bailey


I can't recall exactly why they don't allow overloading on return type (I think it's because return values can be discarded and thus the function wouldn't be distinct), but you can fix the problem with a const_cast hint to the compiler: const std::string& s = const_cast<const Foo&>(foo).GetString();

like image 41
Mark B Avatar answered Jan 17 '23 05:01

Mark B