3

Possible Duplicate:
why isnt it legal to convert (pointer to pointer to non-const) to a (pointer to pointer to a const)

I have am writing a function which takes a 2D array as input, and does not change the underlying values, and I wanted to explicitly specify this in the function declaration. I am a bit confused about this code (which is obviously just a minimal dummy code to illustrate my question):

int doNotChangeA(int const *a){
    return a[0]+3;
}

int doNotChangeC(int const **c){
    return c[0][0]+3;
}

int main(){

    int *a= new int[1];
    a[0]= 5;
    int b= doNotChangeA(a);
    delete []a;

    int **c= new int*[1];
    c[0]= new int[1];
    c[0][0]= 6;
    int d= doNotChangeC(c);
    delete []c[0];
    delete []c;

    return 0;
}

This code produces a compilation error:

cst.cpp:19: error: invalid conversion from ‘int**’ to ‘const int**’
cst.cpp:19: error:   initializing argument 1 of ‘int doNotChangeC(const int**)’

So, I am a bit confused - why is the first part (non-const 1D array passed to doNotChangeA) allowed and the second (non-const 2D array passed to doNotChangeC) not allowed?

Basically what I want to do is have c be int** which points to non-const values as I want to do whatever I want with it before and after calling doNotChangeC. Of course, I could change doNotChangeC to just take int** instead of int const** and this would "fix" the problem, but I want to explicitly show that doNotChangeC does not change the underlying 2-D array.

Is the right thing to do:

int d= doNotChangeC( const_cast<int const**>(c) );

This compiles fine, but I am confused why is this not required for the first part, i.e. 1-D array (doNotChangeA) ?

Thanks

Community
  • 1
  • 1

1 Answers1

2

This would need to be

int doNotChangeC(int const *const *c){
    return c[0][0]+3;
}

Without the extra const, your function would be able to do something like this:

int doNotChangeC(int const **c){
    c[0] = &something_else;
    return c[0][0]+3;
}

Note that this is different from how C works. In C you would still not be able to pass an int ** to a function that takes a int const *const *, because its rules are simpler.

Vaughn Cato
  • 63,448
  • 5
  • 82
  • 132
  • Thanks for the lightning fast response! You are right, it does fix the problem, however I am still a bit confused. Ok, I understand that the additional const states that the pointers to the 1D arrays don't change, so in fact this declaration does completely reflect what I wanted in the first place.But, just out of interest, why is my attempt wrong? What if I wanted to be able to change the pointers, but have them point to const values? – Relja Arandjelović Dec 31 '12 at 16:59
  • I initially downvoted, but then I realised that this is correct for C++ (I was thinking of C where it doesn't help). Therefore, +1! – Oliver Charlesworth Dec 31 '12 at 17:00
  • @OliCharlesworth: Thanks for commenting. I was getting concerned after two downvotes. – Vaughn Cato Dec 31 '12 at 17:02
  • @VaughnCato: No problem. It may be worth pointing out this difference in your answer, to avoid further casual downvoting! (It's actually quite interesting that the two languages differ in this regard.) – Oliver Charlesworth Dec 31 '12 at 17:06
  • @user1939941: If you wanted to do that, you would have to pass in `int const **`. There is a dangerous hole in the type system otherwise. – Vaughn Cato Dec 31 '12 at 17:08
  • But what's wrong with being able to change the value? – David G Dec 31 '12 at 17:11
  • @David: The rationale is here: http://www.parashift.com/c++-faq/constptrptr-conversion.html – Vaughn Cato Dec 31 '12 at 17:18