公开begin()和end()的const和nonconst版本,用智能指针迭代成员向量

Che*_* OT 6 c++ const smart-pointers const-iterator

// 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;
};
Run Code Online (Sandbox Code Playgroud)

// 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.
}
Run Code Online (Sandbox Code Playgroud)

我希望我的CatLibrary公开non-const begin()并且non-const end()客户端可以在其中迭代指向可变Cat的智能指针.而const begin()const end()返回指向不可改变一个迭代器.

然后,当客户端迭代const CatLibrary时,我不担心他可以修改库中Cat的内容.

但是const添加到我的成员函数begin()只会将指针限定为const指针,而不是它指向的Cat.

如果没有涉及指针,带有constness的向量会使迭代器指向具有constness的元素.但我想这个效果也适用于智能指针指向的元素.

我有办法解决我的问题,但我不确定将来使用会发生什么问题.

在const和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;
}
Run Code Online (Sandbox Code Playgroud)

或者是否有另一种解决方案来解决向量中智能指针的这种常量问题?

nh_*_*nh_ 1

在您发布的示例中,不需要 begin() 和 end() 的 const 版本。您可以在基于范围的 for 循环中使用 const 引用,而无需这些函数的 const 版本,并且根本不需要 cat 为 const auto& 来调用 const 成员函数。

如果您的 cat_library 对象本身是 const ,则可能需要 const begin() 和 end() ,但是您无法添加这样的项目。