No implicit conversion from ‘T **’ to ‘const T **’
For a type T, C++ allows an implicit conversion from T* to const T*. This is safe and you most likely used it hundreds of times before (think method calls with const pointer parameters). But if you try it with a double pointer (e.g. implicitly converting T** to const T**) it will fail. gcc for example will tell you something in the lines of:
error: invalid conversion from 'Test**' to 'const Test**'
Have you ever wandered why this is unsafe and wrong and so reported as a compile time error?
Let’s see a small piece of code:
#include <iostream>
class Test
{
public:
Test() : i ( 0 )
{}
void modify_value()
{
i = 100;
}
int get_value() const
{ return i; }
private:
int i;
};
int main()
{
const Test constantObject; // notice the const
std::cout << constantObject.get_value() << std::endl;
Test *pt = 0;
// the constant pointer ppt points to pt
const Test **ppt = /*(const Test **)*/&pt; // !!!!
// this actually makes pt point to the constant object
*ppt = &constantObject;
// pt is not declared as const, so this method call now looks valid
pt->modify_value();
std::cout << constantObject.get_value() << std::endl;
return 0;
}
The above code will generate the error we talked about if you try to compile it. To shut the compiler up uncomment the cast on the line marked with !!!!. Now everything should build and run.
What this code does is declare a constant object (initial value displayed as ’0′), do some stuff that would be possible if the implicit conversion would be allowed, and then display the value of the ‘constant’ object again (which is now ’100′). Cool, huh?
Notes:
- implicit conversion from T ** to const T * const * is safe and allowed.
- never-ever hide a compiler error with a cast, as we did above. You could bring about apocalypse (remember that modifying an object defined as constant by any means leads to undefined behavior).