I've run into some annoying issues with const-correctness in some templated code, that ultimately boils down to the following observation: for some reason, given an STL-ish Container type T, const typename T::pointer
does not actually seem to yield a constant pointer type, even if T::pointer
is equivalent to T::value_type*
.
The following example illustrates the problem. Suppose you have a templated function that takes a Container which must meet the STL Random Access Container concept requirements.
template <class Container>
void example(Container& c)
{
const typename Container::pointer p1 = &c[0]; // Error if c is const
const typename Container::value_type* p2 = &c[0];
}
Then, if we pass this function a const container...
const std::vector<int> vec(10);
example(vec);
...we get an invalid conversion from const int*
to int*
. But why is const typename Container::pointer
not the same as const int*
in this example?
Note that if I change const typename Container::pointer
to simply typename Container::const_pointer
it compiles fine, however, as far as I can tell, the const_pointer typedef is an extension, (I don't see it mentioned in the C++ standard Container Requirements (23.5, Table 65)), and so therefore I don't want to use it.
So how can I obtain a generic, const-correct pointer type from a container T? (I really can't see how to do this without using boost::mpl::if_ along with type_traits to check if the container is constant, but there must be a less verbose way to do this)
In case it matters, I'm using gcc 4.3.2 to compile this.
It doesn't work because your const
does not apply to what you think it applies to. For example, if you have
typedef int* IntPtr;
then
const IntPtr p;
does not stand for
const int* p;
but rather stands for
int* const p;
Typedef-name is not a macro. Once the "pointerness" of the type is wrapped into a typedef-name, there's no way to use it to create a pointer-to-const type anymore. I.e. there's absolutely no way to use the above IntPtr
typedef-name to produce an equivalent of
const int* p;
You have to either use to pointee type explicitly (as you did with value_type
), or check whether your container defines a different typedef-name, with const
already wrapped "inside" (like const_pointer
or something like that).