I’m using the type aliases for pointer and const pointer and I don’t understand why there is difference between returning a cost pointer and a const_pointer.
I assumed that const pointer, in this case, is equivalent to const int*, but I’m getting an invalid conversion compile error:
error: invalid conversion from 'const int*' to 'S::pointer {aka int*}
struct S
{
using pointer = int*;
using const_pointer = const int*;
// const_pointer get() const { return &i; } // OK
const pointer get() const { return &i; } // ERROR
int i = {};
};
int main()
{
const S s;
s.get();
}
>Solution :
I find it helps if you stop putting const on the left. If I rephrase your question:
struct S
{
using pointer = int*;
using const_pointer = int const*;
using pointer_const = int*const;
// const_pointer get() const { return &i; } // OK
// pointer_const get() const { return &i; } // ERROR
pointer const get() const { return &i; } // ERROR
int i = {};
};
int main()
{
const S s;
s.get();
}
I have replaced const int* with int const*. As a general rule in C++, const in a type applies to the component of the type on the left. Only when there is no type on the left does it violate this rule.
When there is no component on the left, it then looks at the local expression of the type – where const is added. It moves "one step right", and follows the apply on the left rule. So:
const pointer
becomes
pointer const
And that becomes
int*const
not
int const*
The second part is understanding that a "pointer to const int" is different than a "const pointer to a non-const int". In one case, we are pointing at something we cannot modify; in the other, we cannot motifiy which object we are pointing to, but we can modify that object.
Once you stop allowing "const on the left" – once you translate (at least in your head) where const is from being on the left to being on the right of the thing it modifies – a lot of the confusion evaporates.
The last part of confusion is that the transformation from "on the left" to "on the right" cares about the type as described where const is, not the full actual expanded type.