3

I have an std::vector<int*> v and I'd like to prevent further writes to it. The C++ compiler does not accept this

const std::vector<const int*>& w = v;

but it accepts this

const std::vector<const int*>& w = reinterpret_cast<const std::vector<const int*>&>(v);

The latter does work with Microsoft's compiler, meaning that the int* inside v and const int* inside w have the same addresses in memory.

Does this work by chance, as an unspecified behavior, or is it valid C++ ? Does it work with all types inside the vector, like std::vector<std::shared_ptr<int>> ? If invalid, is there another way to do this cast ?

I know I could also copy the vector, but I'd like to avoid that, since my vectors are pretty big.

V. Semeria
  • 3,128
  • 1
  • 10
  • 25

1 Answers1

8

This is Undefined Behavior.

std::vector<const int*> and std::vector<int*> are two different classes (generated by the same template, but that is irrelevant). They cannot alias each other and you cannot reinterpret_cast between them.

My solution is to use std::span:

const std::span s{const_cast<const int* const*>(v.data()), v.size()};

This will create a const std::span<const int* const>.

bolov
  • 72,283
  • 15
  • 145
  • 224
  • This is certainly an elegant solution. The `const_cast` makes it somewhat ugly though. It'd be better if we could get rid of that. – Aykhan Hagverdili Dec 22 '20 at 12:52
  • @AyxanHaqverdili yes, there is a way nicer solution: to modify the original variable type. Since that is not possible for OP I feel this is the next best thing. The `const_cast` is not a problem for me because it is used to add const, not remove it. – bolov Dec 22 '20 at 12:54
  • I cannot change the type of the variable, because the vector really is modified up to a certain point in the algorithm, and then it becomes read-only and used as input for the rest of the algorithm. I am in C++14 so I cannot use span, but exposing const getters to the beginning and end of the vector should be enough. Thanks. – V. Semeria Dec 22 '20 at 13:32
  • @bolov do note that adding const like that _is_ dangerous. See [Conversion from int** to const int**](https://stackoverflow.com/q/16390294/10147399). Or else the conversion would have been implicit. – Aykhan Hagverdili Dec 22 '20 at 14:25
  • @Artyer oh wow, I was so wrong. Thank you for pointing it out. Edited. – bolov Dec 22 '20 at 18:15