The following line of code compiles just fine and behaves:
list<const int *> int_pointers; // (1)
The following two lines do not:
typedef int * IntPtr;
list<const IntPtr> int_pointers; // (2)
I get the exact same compile errors for
list<int * const> int_pointers; // (3)
I'm well aware that the last line is not legal since the elements of an STL container need to be assignable. Why is the compiler interpreting (2) to be the same as (3) ?
Short answer:
const (and volatile) should naturally appear after the type they qualify. When you write it before, the compiler automatically rewrites it internally:
const int *
becomes
int const *
which is a pointer to a constant int. Lists of these will compile fine since the pointer itself is still assignable.
You read C-style type declarations right to left. So "const int *" is a pointer to constant ints ("const int" and "int const" mean the same thing). Those are perfectly assignable. But (2) and (3) are constant pointers to int, and therefore not assignable.
You are asking "Why is the compiler interpreting (2) to be the same as (3)?". Well, because in C++ language (as well as in C) they are semantically the same. When you define a typename as
typedef int *IntPtr;
then later the type const IntPtr
will stand for int *const
, not for const int *
. That's just how typedef-names work in C++.
Typedef-names in C++ are not macros. While they do not define new types (just aliases for the existing ones), the resulting aliases are nevertheless "atomic", "monolithic" in a sense that any qualifiers applied to the alias will apply as top-level qualifiers. When you are working with a typedef-name, there's no way to "sneak in" a const qualifier so that it would somehow "descend" to a lower-level portion of the type (int
in your case).
If you insist on using typedef-names, you have no other immediate choice but to provide two different typedef-names, like
typedef int *IntPtr;
typedef const int *ConstIntPtr;
and use ConstIntPtr
when you need a pointer-to-const version of the type.
const IntPtr
and const int*
are not the same thing.
1) const int*
is "pointer to const int
".
2) const IntPtr
expands to int * const
(think (int *) const
) which is "const
pointer to int
".
In short, the typedef
is acting like a set of parentheses. You can't change the const
-ness of what a typedef
'd pointer points to.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With