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 yeild 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)
Edit: 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).
This:
typename Container::pointer
Has the type int*
(in our case). I don't know the terminology, so sorry for that, but pointers point to a type. That is, Container::pointer
is a pointer to a mutable T, and adding const is only going to make this a const pointer (not a pointer to const), because Container::pointer has already been defined to point to a mutable T.
It seems only const_pointer
, either from the class or your own:
typedef const typename Container::value_type* const_pointer
Will work.
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