Reputation: 3290
the below code doesn't compile
void aaa(const int **a) {
}
int *a[] = {new int[2]};
aaa(a);
I got "cannot convert parameter 1 from 'int [1]' to 'const int *" in VS2010 and similar error in gcc
when I change my declaration to:
int const *a[] = {new int[2]};
or
const int *a[] = {new int[2]};
it compiles, but I don't understand why it doesn't accept a non const variable declaration
Upvotes: 1
Views: 1504
Reputation: 153909
The type of a
is int*[]
; the type you want is int const**
.
int*[]
converts to int**
, but this will not convert implicitly to
int const**
. Consider the following code to understand why:
static int const ci = 42;
void aaa( int const** out )
{
*out = &ci;
}
int
main()
{
int* pa;
aaa( &pa ); // NOT LEGAL, because...
*pa = 0; // would now change ci
std::cout << ci << std::endl;
return 0;
}
As you can see, allowing this conversion would break const without requiring a cast.
Depending on what you are doing, you might want to use:
void aaa( int const* const* out );
The implicit conversion of int**
to int const *const *
is legal.
(Otherwise, you'll need a const_cast
somewhere, to tell the compiler
that you know what you're doing, and that it isn't really a problem.)
Upvotes: 8
Reputation: 21779
The function aaa
expects a pointer-to-pointer-to-constant-int.
Your variable a
is a pointer-to-pointer-to-int.
It is an error to assign the latter to the former.
both int const *a[]
and const int *a[]
is actually the same thing, matching the signature of aaa
. If you tried int * const a[]
, that would be a different type (pointer-to-constant-pointer-to-int) and you would trigger the type error again.
If you want your function aaa
to take a constant-pointer-to-pointer-to-int, you need to write aaa(int ** const a)
, but having a const-ness on parameter values has actually no effect on what you can call with.
Edit: "But isn't constness added implicitly - done with an implicit cast? (Which is the actual question)"
Constness can be implicitly added to the value you are passing, e.g.
void aaa(const int a) {}
int b=5;
aaa(b);
... or one level pointer
void aaa(const int* a) {}
int *b=new int;
aaa(b);
... but cannot be added deeper. For example this is invalid:
void aaa(const int** a) {}
int* b=new int;
int** c=&b;
aaa(c);
I think James Kanze explains it much better in his answer.
Upvotes: 2