Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a const function rather than its non-const version

I tried to wrap something similar to Qt's shared data pointers for my purposes, and upon testing I found out that when the const function should be called, its non-const version was chosen instead.

I'm compiling with C++0x options, and here is a minimal code:

struct Data {     int x() const {         return 1;     } };  template <class T> struct container {     container() {         ptr = new T();     }       T & operator*() {         puts("non const data ptr");         return *ptr;     }      T * operator->() {         puts("non const data ptr");         return ptr;     }      const T & operator*() const {         puts("const data ptr");         return *ptr;     }      const T * operator->() const {         puts("const data ptr");         return ptr;     }      T* ptr; };  typedef container<Data> testType;  void testing() {     testType test;     test->x(); } 

As you can see, Data.x is a const function, so the operator -> called should be the const one. And when I comment out the non-const one, it compiles without errors, so it's possible. Yet my terminal prints:

"non const data ptr"

Is it a GCC bug (I have 4.5.2), or is there something I'm missing?

like image 417
coyotte508 Avatar asked Sep 02 '11 17:09

coyotte508


People also ask

Can a non-const function call a const function?

const member functions may be invoked for const and non-const objects. non-const member functions can only be invoked for non-const objects. If a non-const member function is invoked on a const object, it is a compiler error.

How is it possible to have both const and non-const version of a function?

There are legitimate uses of having two member functions with the same name with one const and the other not, such as the begin and end iterator functions, which return non-const iterators on non-const objects, and const iterators on const objects, but if it's casting from const to do something, it smells like fish.

What will happen if a const object calls a non-const member function?

If the function is non-constant, then the function is allowed to change values of the object on which it is being called. So the compiler doesn't allow to create this chance and prevent you to call a non-constant function on a constant object, as constant object means you cannot change anything of it anymore.


2 Answers

If you have two overloads that differ only in their const-ness, then the compiler resolves the call based on whether *this is const or not. In your example code, test is not const, so the non-const overload is called.

If you did this:

testType test; const testType &test2 = test; test2->x(); 

you should see that the other overload gets called, because test2 is const.

like image 177
Oliver Charlesworth Avatar answered Oct 20 '22 14:10

Oliver Charlesworth


test is a non-const object, so the compiler finds the best match: The non-const version. You can apply constness with static_cast though: static_cast<const testType&>(test)->x();

EDIT: As an aside, as you suspected 99.9% of the time you think you've found a compiler bug you should revisit your code as there's probably some weird quirk and the compiler is in fact following the standard.

like image 36
Mark B Avatar answered Oct 20 '22 13:10

Mark B