Note. I wrote this answer under the assumption that T in your question represents some actual data type - I chose int in my examples below.
Background: I tried to pass a const pointer to a function. [...] I have to consider cases in which a local pointer is passed and in which it is temporarily passed (say, from a function call)
You did not say what you mean by "const pointer". At first, I assume that you are referring to a pointer, which in itself is constant (i.e. the address it points to cannot be changed).
According to your description, there are two ways to get such a pointer:
Now you can define a function that accepts these two cases as follows:
void g(int *const &arg) { }
You can apply this as g(p); to a constant, a local pointer, such as p , defined earlier, as well as to a temporary g(f()); . (You could, thirdly, apply it to a non-constant local pointer, because switching from a non-const lvalue to a const lvalue is never a problem.)
This function g has an argument to the arg function, which is defined as a constant, lvalue reference to an int pointer. It can bind to a constant (or really mutable) local pointer (like p ), as well as to a temporary one, because constant references to lvalue, unlike non-constant references to lvalue, can do this.
Note. I don’t understand why in this case you need the function argument to be a reference in general. You can simply declare void g(int *const arg) (without ampersand) and without help. Reasons include: a) you still cannot change it; b) In all realities of the real world, this link will take as much (or as little) as the pointer itself, so it makes no sense to avoid copying.
Anyway. If you want, you can also define a second version of g specifically for links rvalue:
void g(int *&& arg) { }
This can only be applied to a temporary pointer, not to a local pointer, because the function argument is defined as an rvalue reference, which can bind to temporary, but not lvalues.
However, if by “const pointer” you actually mean “pointer-to-const”, that is, a pointer that can be changed to different addresses, but does not have the right to change the value stored at these addresses, the declarations are slightly different. The const keyword should be placed in front of the asterisk, and for best clarity, it is best before the specifier of type int :
// Declare local pointer-to-const: const int *p = 0; // Function that returns a pointer-to-const: const int *f() { return 0; }
A function that can take these two will then be declared as:
void g(const int *const &arg) { }
The first const means that we are talking about constant pointers, and the second const ensures that we have the lvalue-reference constant, which can communicate with both rvalues and lvalues. Note that this function cannot change what arg indicates, because arg declared as a constant lvalue reference. In the case where arg binds to the temporary, this is probably what we want anyway (as stated above). But in the case when the function is called as g(p); , we might want to change the local pointer p from g . If you want g have this power, you need to define two versions:
void g(const int *&& arg) { } void g(const int *& arg) { }
Note 1: Your initial declaration of const int *const &const useless (and not even accepted by GCC). This would mean "a constant reference to a constant pointer to an int constant", but since the reference to a constant pointer is not a constant reference in itself, the final const is redundant (and is not provided by the standard).
Note 2: The universal reference does not coincide with the reference to the rvalue. Universal references are declared as T &&arg , where T is a template parameter. Depending on what T refers to each instance of the template, it may be a reference to an lvalue or a reference value of rvalue, therefore, its “universal” symbol. In any case, this has nothing to do with your use case, since you are dealing with T * pointers here (even if we assume that T is a template parameter).