Brushing up knowledge regarding (multidimensional) arrays / pointers conversions, the following two rules can explain some illegal conversions:
- An T[M][N]decays to aT(*)[N], but not to aT**(as is explained in this SO entry)
- There is not implicit conversion from T**toconst T**(as is explained in the C++ faq)
So here is some test code written to try to cover different cases. The 3 cases we cannot explain are annotated with P1, P2 and P3.
int main() {
    {
        int arrayOfInt[3] = {0, 1, 2};
        int * toPtr{nullptr};
        int ** toPtrPtr{nullptr};
        const int ** toPtrPtrConst{nullptr};
        toPtr = arrayOfInt;
        //toPtrPtr = &arrayOfInt; //KO, I assume because of 1.
        //toPtrPtr = static_cast<int**>(&arrayOfInt); //KO, same as above
        toPtrPtr = reinterpret_cast<int**>(&arrayOfInt);
        toPtrPtr = (int**)&arrayOfInt;
        //toPtrPtrConst = &arrayOfInt; //KO, still 1.
        //toPtrPtrConst = static_cast<const int**>(&arrayOfInt); //KO, still 1.
        toPtrPtrConst = reinterpret_cast<const int**>(&arrayOfInt); // (P1)
            // it is supposed to be allowed to cast int** to const int* const*
            // not const int**
            // Why is it working without requiring a const_cast
            // to cast away the const qualifier?
        toPtrPtrConst = (const int**)&arrayOfInt;
        //toPtrPtrConst = toPtrPtr; //KO, because of 2.
        //toPtrPtrConst = reinterpret_cast<const int**>(toPtrPtr); //KO because of 2.
            // so why is P1 allowed?
    }
    {
        const int arrayOfConstInt[3] = {0, 1, 2};
        const int * toPtrConst{nullptr};
        const int ** toPtrPtrConst{nullptr};
        int * const * toPtrConstPtr{nullptr};
        toPtrConst = arrayOfConstInt;
        //toPtrPtrConst = &arrayOfConstInt; //KO, I assume because of 1.
        //toPtrPtrConst = static_cast<const int**>(&arrayOfConstInt); //KO, same as above
        //toPtrPtrConst = reinterpret_cast<const int**>(&arrayOfConstInt); // (P2) 
            // Compiler error "casts away qualifiers",
            // but which qualifier(s) would that cast away?
        toPtrPtrConst = (const int**)&arrayOfConstInt;
        //toPtrConstPtr = &arrayOfConstInt; //KO, I assume because of 1.
        //toPtrConstPtr = static_cast<int * const *>(&arrayOfConstInt); //KO, same as above
        toPtrConstPtr = reinterpret_cast<int * const *>(&arrayOfConstInt); // (P3) 
            // This one actually drops the const qualifier on the integer,
            // but nevertheless it compiles
        toPtrConstPtr = (int * const *)&arrayOfConstInt;
        toPtrConstPtr = reinterpret_cast<int * const *>(&toPtrConst); // KO
            // because it casts away const qualifier
            // so why is P3 allowed?
    }
}
Here it is in ideone: http://ideone.com/JzWmAJ
- Why P1 allowed while it seems to violate 2.?
- What are the qualifier(s) cast away by P2?
- Why is P3 allowed when it actually casts away a const qualifier?
 
     
     
    