0

So I have been reading Programming Principles and Practices in C++ by Bjarne. And the section on conversion of templated objects of base/derived classes got me kinda confused. So I tried to try out different combinations and stumbled on something weird

#include <iostream>

class A {
public:
    int i;
};

class B : public A {
    int j;
};

template<typename T>
class Array_ref{
public:

    Array_ref(T* pointer, int size) : p{pointer}, sz{size} {}
    template<typename Q>
    operator Array_ref<const Q>(){
        static_cast<Q>(*static_cast<T*>(nullptr));
        return Array_ref<const Q>{reinterpret_cast<Q*>(p), sz};
    }
    T& operator[](int n){ 
        return p[n];
    }
private:
    T* p;
    int sz;
};

void test_function(Array_ref<A* const> temp){
    if(temp[0]->i)
        std::cout<<"failed I guess"<<std::endl;
    exit(0);
};

int main(){
    B* testobj[1];
    testobj[0] = new B;
    testobj[0]->i = 0;
    Array_ref<B*> a(testobj, 1);
    test_function(a);
    delete testobj[0];
    exit(0);
}

The void test_function(Array_ref<A* const> temp) is the line that troubled me. Since if I made it Array_ref<const A*> it fails to compile with the error that it can't convert from B* to const A*, though as far as I know, I have provided the conversion rule which should fit the overloading arguments. In fact, aren't const A* and A* const very different things?

I would be glad if someone can help me out with where I am messing up, and what I missed out. Thanks a bunch!

1 Answers1

0

Yes, const A* and A* const are very different things, and that's why your conversion operator Array_ref<const Q> cannot fulfill a parameter of type Array_ref<const A*>.

If Q = A*, then const Q = Q const = A* const.

jtbandes
  • 115,675
  • 35
  • 233
  • 266
  • `const Q` and `Q const` are completely equivalent. See: https://stackoverflow.com/questions/44190328/const-b-and-const-a-are-incompatible-even-when-b-is-aliased-to-a?noredirect=1&lq=1 – jtbandes May 11 '20 at 18:52