32

I have a member variable of type vector<T> (where is T is a custom class, but it could be int as well.) I have a function from which I want to return a pointer to this vector, but I don't want the caller to be able to change the vector or it's items. So I want the return type to be const vector<const T>*

None of the casting methods I tried worked. The compiler keeps complaining that T is not compatible with const T.

Here's some code that demonstrates the gist of what I'm trying to do;

vector<int> a;
const vector<const int>* b = (const vector<const int>* ) (&a);

This code doesn't compile for me.

Thanks in advance!

user345386
  • 323
  • 1
  • 3
  • 6

5 Answers5

30

If you have a const vector<int> you cannot modify the container, nor can you modify any of the elements in the container. You don't need a const vector<const int> to achieve those semantics.

James McNellis
  • 348,265
  • 75
  • 913
  • 977
17

On why a vector<T> cannot be correctly converted to a vector<const T> even if T can be converted to const T

This is a common recurring problem in programming whether it is with constness or inheritance (a container of derived object cannot be converted to a container of base objects, even if the contained elements themselves can). The problem is that element by element each one of them can be converted, but the container itself cannot without breaking the type system.

If you were allowed to do vector< const T > &vr = my_vector_of_T, then you would be allowed to add elements through vr, and those elements would be constant by definition. But at the same time those same elements would be aliased in my_vector_of_T as non-const elements and could be modified through that interface, breaking constness in the typesystem.

In the particular case of a vector<int> being converted to a vector<const int>, chances are that you would not notice really weird effects --besides adding an element to a vector<const int> and seeing how the constant element changes in time, but still remember that given two related types T1 and T2 for which a relation exists, in most cases trying to apply the same relationship to containers of T1 and T2 will break the type system.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
16

In addition to James's answer about how to do it you should note that const int is not a valid type to put into any standard container since it is not assignable.

Edward Strange
  • 40,307
  • 7
  • 73
  • 125
1

you can force conversion like this:

b = reinterpret_cast<const std::vector<const int>*>(&a);

but I do not think you should do this, since it is not guaranteed to work, only to compile

Anycorn
  • 50,217
  • 42
  • 167
  • 261
  • 2
    Since the OP used a c-style cast this is actually effectively what they tried to do. A c-style cast will do a reinterpret cast when the types are unrelated and vector is unrelated to vector or anything else. – Edward Strange May 19 '10 at 19:15
1

The compiler decides to block this. However, we know this is safe so maybe we can fool it:

const vector<const int>* b = (const vector<const int>* )(void *)(&a);
Joshua
  • 40,822
  • 8
  • 72
  • 132
  • 4
    Well, it's not safe. The type `std::vector` is invalid because `std::vector` requires that T is assignable and `const int` isn't. – MSalters May 20 '10 at 09:00
  • The funny thing is I used a compiler that would compile this until you tried to write to the vector then you get a really obscure compiler error. – Joshua May 20 '10 at 18:08
  • "we know this is safe" - haha, wow! "safe" is never, not once, an appropriate thing to say about `reinterpret_cast` to anything except `[un/signed] char const *`. Everything else is implementation-defined if you're _lucky_ and are willing to write brittle non-portable code. Besides, (A) `T const` is not a valid element type, and (B) even if it were, the Standard need not put the 2 instantiations' member variables in the same order, so even if `reinterpret_cast` did reinterpret object representation on your compiler, it's folly to assume compatible members live at equivalent offsets within both – underscore_d Jul 08 '16 at 23:22