Calling a const function rather than its non-const version

23,442

Solution 1

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.

Solution 2

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.

Share:
23,442
coyotte508
Author by

coyotte508

loves abusing C++, assembler, C++0X, C and C99 features all in the same code, all in moderation. goto abuse, exception abuse in normal code, variable length arrays, pointers to virtual functions, variadic macros, variadic templates, SFINAE, decltype, CRTP, coroutines, and all kind of hacks. I've yet to use Objective C in C++ code.

Updated on July 09, 2022

Comments

  • coyotte508
    coyotte508 almost 2 years

    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?