开发者

C++ : struggle with generic const pointer

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 Contai开发者_运维技巧ner::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.


The allocator requirements (cf. 20.1.5, Table 32, "Allocator requirements") state that allocators for the STL containers shall have an Allocator::const_pointer. All of the STL containers (the eight containers listed in Section 23) define a Container::const_pointer typedef as:

typedef typename Allocator::const_pointer const_pointer;

As you state in your question, however, containers (other than those eight) are not required to have a Container::const_pointer typedef.


This might be of relevance here (from SGI STL reference):

[6] As in the case of references [5], the pointer type must have the same semantics as C++ pointers but need not actually be a C++ pointer. "Smart pointers," however, unlike "smart references", are possible. This is because it is possible for user-defined types to define the dereference operator and the pointer member access operator, operator* and operator->.


It is possible by using a template. The trick is to remove the pointer first, then apply const on the type and finally applying pointer to the type - for instance using std::remove_pointer yields:

typedef const std::remove_pointer<Container::pointer>::type* PointerToConst;
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜