0

I want to write a function that modifies a given pointer of any type; thus I declared my function to accept a void*&, relying on the implicit conversion from any pointer to void*. However the following code refuses to compile, saying it can't convert int*to void*&.

void f(void*& x)
{   
     x = 0; 
}

int main() {

    int* a = new int;
    f(a);
    delete a;
    return 0;
}

Note that it works fine if f is declared as accepting an int*& (but then loses its generality) or if f is declared as accepting a void* ( but then f can only modify its argument locally).

So independently the "any T* to void*" implicit conversion rule works, the "T to T& implicit conversion rule works, but not both at the same time ? Why is that so ? What did I got wrong here ?

(I know I could use a template function for f, this is mostly out of curiosity).

Louen
  • 3,617
  • 1
  • 29
  • 49
  • http://stackoverflow.com/questions/399003/is-the-sizeofsome-pointer-always-equal-to-four "no guarantee that sizeof(int *) == sizeof(double *)" - so there's no way to generate non-templated code that does what you want. – Karoly Horvath Oct 07 '13 at 11:29
  • @KarolyHorvath: `void*` is always big enough to hold any object pointer. It also is debatable if the possible size difference (that is nowhere seen in real implementations btw.) of object pointers is real and intended, or just a picky interpretation of scattered standard wording. – PlasmaHH Oct 07 '13 at 11:34
  • @PlasmaHH: I'm not sure what you intended to convey with this... should the code just zero the memory location for a void* (which is big enough), potentially overwriting the memory location of another variable? – Karoly Horvath Oct 07 '13 at 11:35
  • @KarolyHorvath: besides that it doesn't compile (because temporaries can not bind to non-const references), if it would be legal, it would most likely do the intended thing because the possible difference in sizes of object pointers is purely theoretical, as is speculating about the possible behaviour of an illegal language construct. – PlasmaHH Oct 07 '13 at 11:43
  • 1
    Consider the case that instead of `0` in `f` you wrote `new std::vector`. Do you see how safe that conversion would actually be? – molbdnilo Oct 07 '13 at 11:44
  • what you're referring to as "purely theoretical" is called the standard. I think we perfectly understood each other from the beginning so this whole conversation is pointless. – Karoly Horvath Oct 07 '13 at 11:59

2 Answers2

2

It's because the reference bit. A reference to a pointer to one type is not the same as a reference to a pointer of another type.

This can of course be solved by using templates:

template<typename T>
void f(T*& x) { ... }
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
0

If it would work here, you would create a temporary void* out of the T* (since conversion here really means "create a new object of another type") which you then would bind a reference to, which won't work, since it is non-const. What would work though is:

void f(void* const & x)
{   
     x = 0; 
}

But this is likely not what you intended, since it is referring to the temporary, not the int*.

PlasmaHH
  • 15,673
  • 5
  • 44
  • 57