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?