Question

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

Was it helpful?

Solution

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.)

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top