5
votes

For learning purposes, I've written the following code:

void Swap(const int *&Pointer1, const int *&Pointer2)
{
    const int *Tmp = Pointer2;
    Pointer2 = Pointer1;
    Pointer1 = Tmp;
}

I have a few doubts about this code and how top/low level constness works in such cases, with 3 or more "levels".

  1. Obviously my references can't be const, otherwise I wouldn't be able to swap the pointers. Let's suppose however that the code would not touch the pointers values (the adresses they contain): the right syntax would be const int *(const &Pointer) or int * const &Pointer? I have the feeling the latter would mean "reference to a const pointer to const int, but I'm not sure. And if that is the case, the const part would be ignored by the compiler like a more simple const int pass by value or would not because it is under a reference?
  2. Trying to call this function with pointer to int fails. However, it is possible to assign an int adress to pointer to const int and indeed I get no error if I simply remove the references. This makes me think that those references "forces" every const to perfectly match. Is this true? And if so, there is some way around it?
2
It might help to know that the const keyword is applied to the thing on the left, unless there is nothing on the left in which case it will be applied to the thing on the right, in your example it is applied to the int not the int*. See: duramecho.com/ComputerInformation/WhyHowCppConst.htmlAdaRaider
In order to swap int * and const int * you will need two separate functions or a template because a reference to int * and a reference to const int * are not related even though int * can be converted to const int *user7860670
Suppose that you were able to convert int* to const int*&. Then you could int* p; const int*& y = p; const int x = 0; y = &x; *p = 1; and modify a const object.molbdnilo
You can use this site to check right syntax for complex combinations of pointers and const.Serikov

2 Answers

4
votes
  1. If you want Pointer to be const too, then it would be int const * const & Pointer, let's read it from right to left; so Pointer is a reference to const pointer to const int. (Note that means both Pointer itself and the int pointed by Pointer can't be changed either. This might conflict the intent of Swap.) And both the two const parts won't be ignored when pass-by-reference. Unlike pass-by-value, reference can't be top-level const qualified, and constness qualifed on what it refers to is reserved.

  2. You can't pass int * to the function taking const int *& (i.e. lvalue-reference to non-const pointer). int * could convert to const int* implicitly, but the converted const int* is a temporary, which can't be bound to lvalue-reference to non-const. Temporary could be bound to lvalue-reference to const (or rvalue-reference), so change the parameter type to int const * const & Pointer as stated in #1, passing int * would be fine.

-2
votes
template <class P1,class P2>
void Swap(P1 && Pointer1, P2 && Pointer2)
{/*...*/}

int main()
{
    const int a =1, b = 2;
    Swap(&a, &b); // &a and &b - r-value, Pointer1 and Pointer2 param this 'const int* &&'
    const int * const a_cref_p = &a;
    const int * const b_cref_p = &b;
    Swap(a_cref_p,b_cref_p); // a_cref_p and b_cref_p - l-value, Pointer1 and Pointer2 param this 'const int* const &'
    const int * a_ref_p = &a;
    const int * b_ref_p = &b;
    Swap(a_ref_p,b_ref_p); // a_ref_p and b_ref_p - l-value, Pointer1 and Pointer2 param this 'const int* &'
    return 0;
}