C++
I want to know if a pointer that isn’t already a two-const
pointer (e.g. T const * const
) can be implicitly or explicitly cast, processed through something (e.g. a function), or otherwise converted, to yield a T const * const
, without or before being used to initialize a variable that is declared as a T const * const
. How can I do this?
I thought that if I started with a T*
, then one const_cast
(or two, in case the cast can only cast in one const
at a time) would suffice, but apparently it doesn’t. Many variables in the code show a different unsuccessful attempt at yielding T const * const
through casting or returning from a function. Every cast failed to return a pointer with a trailing const
. (I refer to the const
to the left of *
as the leading const
and the one to the right of *
as the trailing const
.) Because of the unsuccessful casts, I tried unsuccessfully to force the const
through direct initialization. This was compiled in VC11
. g++ on stack-crooked.com gives a logically equivalent console output, albeit with different names for typeid(/*...*/).name()
.
#include <iostream>
#include <typeinfo>
using namespace std;
int const * const foo()
{
return nullptr;
}
int main()
{
int x = 7;
auto a1 = &x;
cout << typeid(a1).name() << endl;
auto a2 = const_cast<int const *>(&x);
cout << typeid(a2).name() << endl;
auto a3 = const_cast<int * const>(&x);
cout << typeid(a3).name() << endl;
auto a4 = const_cast<int const * const>(&x);
cout << typeid(a4).name() << endl;
auto a5 = const_cast<int const * const>(a4);
cout << typeid(a5).name() << endl;
auto a6 = (int const * const) &x;
cout << typeid(a6).name() << endl;
auto a7 = static_cast<int const * const>(a4);
cout << typeid(a7).name() << endl;
auto a8 = reinterpret_cast<int const * const>(a4);
cout << typeid(a8).name() << endl;
auto a9 = foo();
cout << typeid(a9).name() << endl;
int const * const a10 = &x;
cout << typeid(a10).name() << endl;
cout << ( typeid(a10) == typeid(a4) ) << endl;
auto a12 = a10;
cout << typeid(a12).name() << endl;
cout << ( typeid(a12) == typeid(a4) ) << endl;
}
Expected results vs. actual results, and questions:
Question numbers correspond to the same-numbered a#
variables.
- Got expected result
int *
- Got expected result
int const *
- Expected
int* const
, but gotint*
. Did theconst_cast
ignore its trailingconst
argument and why? Since the return is the same constness and type as the argument, did the cast run at all? - Expected
int const * const
, but gotint const*
. Did theconst_cast
ignore its trailingconst
argument and why? - I wanted to see if
const_cast<int const * const>
will include a trailingconst
in the result given that the argumenta4
already has a leadingconst
. Expectedint const * const
. Gotint const*
. Did theconst_cast
ignore its trailingconst
argument and why? - Expected
int const * const
. Gotint const*
. Why would the explicit cast still exclude the trailingconst
? - Expected
int const * const
. Gotint const*
. Why would thestatic_cast
exclude the trailingconst
? - Expected
int const * const
. Gotint const*
. Why would thereinterpret_cast
exclude the trailingconst
? - Expected
int const * const
. Gotint const*
. Why would an initialization to theint const * const
return of a function still exclude the trailingconst
in the result? - Expected
int const * const
. Gotint const*
from the console output but not from the debugger.a10
is explicitly declared asint const * const
, so why does thetypeid().name()
exclude the trailing const?operator==
yields1
, so why is thetypeid()
itself (not just the name) fora10
equivalent to that ofa4
? The VC11 debugger listsa10
’s type asint const * const
. Why is it different than the one fromtypeid()
andtypeid().name()
? Which one is correct? - variable name
a11
omitted because it looks like the word “all”. - I expected
a12
to beint const * const
because it is initialized toa10
, which was explicitly declaredint const * const
.operator==
yields1
, sotypeid()
is stillint const*
. Gotint const*
from both the console output and the debugger. Why are they different from the expected result?
Are all casts, function returns, and initializations limited to only casting in one const
at a time? Is the leading const
the only thing they can cast in?