const with a double pointer

Started by
12 comments, last by Nyarlath 15 years, 9 months ago
I'm a bit confused about how to handle const with a double pointer. I have a function which needs to take a pointer to a u8* so it can change the location the pointer points to, but it does not actually modify any data pointed to by the u8*, so I have made it const, like so:
void foo(const u8** ptr)
{
    // ...do something useful...
    *ptr += some_int;
}
This compiles just fine, but I cannot pass a non-const pointer to it, as the compiler won't automatically promote it to const:
void bar()
{
    u8 *hoge;
    foo(&hoge);   // <- cannot convert parameter 1 from 'u8 **__w64 ' to 'const u8 **'
}
According to the CPP FAQ Lite this isn't allowed, and the solution is to use this format instead:
void foo(const u8* const* ptr)
Unfortunately doing so makes the pointer ptr const as well, and I get a compile error telling me that *ptr += some_int; is const and can't be modified. What is the best solution to this problem?
Advertisement
Quote:What is the best solution to this problem?

Remove the const, also there is no need to pass a pointer to pointer as a reference to pointer will do what you want and is more pleasing on the eye.
void foo(unsigned char *& ptr){    ptr += 1;}int main(){    unsigned char hoge[2];    unsigned char* f(hoge);    foo(f);  }
You need an explicit const cast. You can write an "intermediate" function who does this for you (which will hopefully be inlined).

void foo(const int** a){  // ...do something useful...  *a += 1;}void foo(int** a){  const int** b = const_cast<const int **>(a);  foo(b);}int main(){  int v = 0;  int* c = &v;  foo(&c);}


Or better, as CmpDev suggested, with references:

void foo(const int*& a){  // ...do something useful...  a += 1;}void foo(int*& a){  const int*& b = const_cast<const int *&>(a);  foo(b);}int main(){  int v = 0;  int* c = &v;  foo(c);}


CmpDev: Unfortunately the const keyword is required, as the function will be passed pointers to consts (which I guess I didn't clarify).

Nyarlath: Thanks, I just went with the const_cast wrapper function for now. It seems a bit hacky, but it works. :)

Anyone else have any other ideas?
Quote:Original post by bpoint
CmpDev: Unfortunately the const keyword is required, as the function will be passed pointers to consts (which I guess I didn't clarify).

In that case I fail to see the problem, could you give a working(or non working) example?
Quote:Original post by CmpDev
Quote:Original post by bpoint
CmpDev: Unfortunately the const keyword is required, as the function will be passed pointers to consts (which I guess I didn't clarify).

In that case I fail to see the problem, could you give a working(or non working) example?

foo( double *&ptr );const double *v;foo( v ); // Compile error: cannot convert from const double* to non-const double*&

Or at least, that's how I understand it. Honestly, it smells more like a design problem than anything -- why are you changing const pointers? If you need to change them, why are they const?
Quote:Original post by CmpDev
In that case I fail to see the problem, could you give a working(or non working) example?


void foo(unsigned char *& ptr){	ptr += 1;}int main(){	unsigned char hoge[2];	unsigned char* f(hoge);	const unsigned char* g(hoge);	foo(f);  	foo(g);    // error C2664: 'foo' : cannot convert parameter 1 from 'const unsigned char *' to 'unsigned char *&'}


Edit: Mushu beat me to it. :)

Quote:Original post by Mushu
Honestly, it smells more like a design problem than anything -- why are you changing const pointers? If you need to change them, why are they const?


All I need to do is advance a pointer through const data. The function itself does not modify the data, hence the reason it's const.

Technically I could use the return value for the advanced pointer, and avoid the double pointer entirely, but I'm already using the return value for something else.

If you have any other suggestions, I'm open to them.
Quote:Original post by bpoint
Quote:Original post by CmpDev
In that case I fail to see the problem, could you give a working(or non working) example?


void foo(const unsigned char *& ptr){	ptr += 1;}int main(){	unsigned char hoge[2];	const unsigned char* g(hoge);	foo(g);}


Solved! [smile]

You cannot safely convert a T*& to a const T*&: it's forbidden by the language because it allows you to violate const-safety (simply assign a const-pointer to the second reference, and then modify it using the first reference). Therefore, since you intend to give up const-safety, using const_cast locally is your best bet. I do insist on locally: if you hide it in a function, you won't be able to check const-safety manually where the function is called.


As ToohrVyk points out there is no problem, try rereading this thread.
You start off with a function signature void foo(const u8** ptr) and later say you are passing pointers to const, there is no problem there.
You then change your code so that it will fail? :confused
At CmpDev: I am sorry for being arrogant, but "try rereading this thread".

Quote:Original post by Mushu

foo( double *&ptr );
const double *v;
foo( v ); // Compile error: cannot convert from const double* to non-const double*&

LOL, this is NOT the problem, and it is not like bpoint himself exposed it in its last post. He does not want to remove constness, but add it (implicitely, I would add). So:

Quote:foo( const double *&ptr );
double *v;
foo( v ); // Compile error: cannot convert from non-const double* to const double*&


The solution of ToohrVyk still force a boring conversion every time the function is called AND the non-const pointer is not modified by the function. This code would fail to work correctly (it compiles does not mean that the problem is solved):

// ToohrVyk disadvantageunsigned char[] realdata = { 1, 2, 3 };unsigned char* modifier = realdata;*modifier = 4;const unsigned char* argument(modifier);foo(argument); // this is expected to advance the pointer by one*modifier = 5; // "modifier" still points to the first element// "argument" is useless because it points to const // (a const-cast here is not that sweet,//  and manually move modifier makes less sense of calling foo)


With "my" solution, you call "foo(modifier)" sparing the declaration of "argument", and after the call "modifier" is moved as the reference paramenter promises.

This topic is closed to new replies.

Advertisement