I use VC++. The third line generates a compilation error: "cannot convert from int** to const int**. Conversion loses qualfiers." Why is the conversion not allowed? Isnt it like passing a pointer to a function that takes pointer-to-const (which does work, as far as I know)?
Because the const on the receiving pointer is at a deeper level of indirection than the one on the other end.
You can implicitly convert from (T *) to (T const *), but that's not what you're trying to do, here. You're trying to convert from (T *) to (T const **), which isn't the same.
You could, however, convert to (int * const *).
I'm not converting from T* to T const**. I'm converting from T**, which a pointer to pointer to T, to const T**, which is a pointer to pointer to const T, as far as I know. The receiving pointer is "more limited" than the other pointer (T variables cannot be edited through it). It can't do anything *p can't do. So why is the conversion invalid? It's like converting T* to const T* - the const T* pointer can't override T* 's limitations (because T* is unlimited: it can read and write any non-const T variable), so the comversion is allowed. I know conversion from const to non-const is not allowed because it removes the write-protection, but this is not the case.
'const T *' and 'T const *' mean exactly the same. In fact, the second form is more general.
Again: (T *)->(T const *) can be done implicitly. If we apply that rule to your code, we see that T==(int *) before conversion. Therefore, you can implicitly convert ((int *) *) -> ((int *) const *). You can't convert to ((int const *) *) because that would change T; it would change the type pointed to, which the constness conversion doesn't allow. If you could (int **)->(int const **) implicitly, you could cast anything to anything implicitly.
But convertion from T* to const T* changes the type pointer to too...
And there's no danger in converting from T** to const T**. It doesn't really affect the type pointed to. I mean, it changes from T* to const T*. The same pointer, but with const it can't write T variables, only read them. So why does the constness conversion not allow that, while is does allow changing the type pointed to from T to const T?
Think of the const not as applying to the pointed-to data, but to the pointer. What it means is "dereferencing this pointer doesn't give an l-value". That's why you can cast T * to T const *; because all l-values are r-values. By this logic, the const is part of the pointer type, not of the pointed type.
Let's take a look at int const **. The type means "a pointer to [a pointer to [an int] that cannot be modified]". "A pointer to [an int] that cannot be modified" is as different from "a pointer to [an int]" as it is from "a pointer to [anything]". Allowing the implicit cast of int ** to int const ** would also allow the implicit cast of anything to anything.