If I have the following:
class Animal {};
class Penguin : public Animal {};
class Snake : public Animal {};
class Zoo
{
std::vector<std::shared_ptr<Animal>> animals;
public:
const std::vector<std::shared_ptr<Animal>>& GetAnimals() { return animals; }
std::shared_ptr<Penguin> AddPenguin()
{
auto result = std::make_shared<Penguin>();
animals.push_back(result);
return result;
}
std::shared_ptr<Snake> AddSnake()
{
auto result = std::make_shared<Snake>();
animals.push_back(result);
return result;
}
};
I'd like to keep const correctness, and be able to add the following method:
const std::vector<std::shared_ptr<const Animal>>& GetAnimals() const
{
return animals;
}
However, that doesn't compile because the return type doesn't match animals. As the const
is embedded deep in the type, const_cast isn't able to convert.
However, this compiles and appears to behave:
const std::vector<std::shared_ptr<const Animal>>& GetAnimals() const
{
return reinterpret_cast<const std::vector<std::shared_ptr<const Animal>>&>(animals);
}
I realize reinterpret_cast
s can be dangerous, but are there any dangers to use it in this scenario? Do the types being cast between have the same memory layout? Is the only effect of this to prevent the caller from then calling any non-const methods of Animal?
Update
I've realized this isn't entirely const correct. The caller could call .reset()
on one of the elements of the vector, which would still modify the zoo. Even so, I'm still intrigued what the answer is.
Update on the update I got that wrong, the code I was trying accidentally copied the shared_ptr and so the shared_ptr in the vector can't be reset when the vector is const.