// Cat.h
class Cat
{public:
void const_meow() const{ ... };
void meow(){ ... };
};
class CatLibrary
{public:
std::vector<std::shared_ptr<Cat>>::iterator begin()
{
return m_cat_list.begin();
}
// compile error, the compiler complains cannot covert type
// from `std::vector<std::shared_ptr<Cat>>::const_iterator`
// to `std::vector<std::shared_ptr<const Cat>>::const_iterator`
std::vector<std::shared_ptr<const Cat>>::const_iterator begin() const
{
return m_cat_list.cbegin();
}
private:
std::vector<std::shared_ptr<Cat>> m_cat_list;
};
// main.cpp
CatLibrary cat_library;
cat_library.add(std::make_shared<Cat>());
cat_library.add(std::make_shared<Cat>());
for(auto& cat: cat_library )
{
cat->const_meow();
cat->meow();
}
for(const auto& cat: cat_library)
{
cat->const_meow();
cat->meow(); // hope to compile error due to invoking non_const method of Cat.
}
const CatLibrary& const_cat_library = cat_library;
for(auto& cat: const_cat_library )
{
cat->const_meow();
cat->meow(); // hope to compile error due to invoking non_const method of Cat.
}
const CatLibrary& const_cat_library = cat_library;
for(const auto& cat: const_cat_library )
{
cat->const_meow();
cat->meow(); // hope to compile error due to invoking non_const method of Cat.
}
I want my CatLibrary expose the non-const begin()
and non-const end()
in which a client can iterate the smart pointer pointing to the mutable Cat. And the const begin()
and const end()
return the iterator which points the immutable one.
Then when the client iterates the const CatLibrary, I would not worry he could modify the content of Cat in library.
But the const
added to my member function begin()
only qualifies the pointer to be a const pointer, not the Cat it points.
Without the pointer involved, the vector with constness makes the iterator point to a element with constness also. But I want this effect also applies the element pointed by smart pointer.
I have a approach to solve my problem, but I am not sure what problems would happen in future use.
Maintain two vectors in const and nonconst
#include <iostream>
#include <memory>
#include <vector>
class Cat
{public:
void const_meow() const { std::cout << "meow" << std::endl;}
void meow() { std::cout << "meow" << std::endl;}
};
class CatLibrary
{public:
void add(std::shared_ptr<Cat> cat)
{
m_cat_list.push_back(cat);
m_cat_const_list.push_back(cat);
};
std::vector<std::shared_ptr<Cat>>::const_iterator begin()
{
return m_cat_list.begin();
}
std::vector<std::shared_ptr<const Cat>>::const_iterator begin() const
{
return m_cat_const_list.begin();
}
std::vector<std::shared_ptr<Cat>>::const_iterator end()
{
return m_cat_list.end();
}
std::vector<std::shared_ptr<const Cat>>::const_iterator end() const
{
return m_cat_const_list.end();
}
private:
std::vector<std::shared_ptr<Cat>> m_cat_list;
std::vector<std::shared_ptr<const Cat>> m_cat_const_list;
};
int main()
{
CatLibrary cat_library;
cat_library.add(std::make_shared<Cat>());
cat_library.add(std::make_shared<Cat>());
cat_library.add(std::make_shared<Cat>());
const CatLibrary& const_cat_library = cat_library;
for(auto& cat: cat_library)
{
cat->meow();
}
return 0;
}
Or is there another solution to solve this kind of constness problem on smart pointer in vector?