Give access to encapsulated container

后端 未结 6 1232
借酒劲吻你
借酒劲吻你 2021-01-13 02:38
class X {
  public:
    typedef std::list Container;

    // (1)
    const Container& GetElements() const;

    // (2)
    Container::iterator Element         


        
相关标签:
6条回答
  • 2021-01-13 03:16

    If you can use Boost, there is a library for you: http://www.boost.org/doc/libs/1_47_0/libs/iterator/doc/index.html Specifically look at iterator_facade and iterator_adapter

    Here is an example of what to do - It provides an std::vector holder, with STL compatible iterators. You can extend it by adding other methods, like operator[], size(), push_back() etc.

    template class VectorHolder { public: typedef T value_type;

    public: VectorHolder() : m_values() { }

    public: typedef typename std::vector::iterator vector_iterator; typedef typename std::vector::const_iterator vector_const_iterator;

    class iterator : public boost::iterator_adaptor<iterator, vector_iterator>
    {
    public:
        iterator()
            : iterator::iterator_adaptor_()
        {
        }
    
        iterator(const vector_iterator& it)
            : iterator::iterator_adaptor_(it)
        {
        }
    
    private:
        friend class boost::iterator_core_access;
    };
    
    class const_iterator : public boost::iterator_adaptor<const_iterator, vector_const_iterator>
    {
    public:
        const_iterator()
            : const_iterator::iterator_adaptor_()
        {
        }
    
        const_iterator(const vector_const_iterator& it)
            : const_iterator::iterator_adaptor_(it)
        {
        }
    
        const_iterator(const iterator& it)
            : const_iterator::iterator_adaptor_(it.base())
        {
        }
    private:
        friend class boost::iterator_core_access;
    };
    
    
    iterator begin()
    {
        return iterator(m_values.begin());
    }
    
    iterator end()
    {
        return iterator(m_values.end());
    }
    
    const_iterator begin() const
    {
        return const_iterator(m_values.begin());
    }
    
    const_iterator end() const
    {
        return const_iterator(m_values.end());
    }protected:
    std::vector<T> m_values;};
    
    0 讨论(0)
  • 2021-01-13 03:20

    Off course, the simplest is this :

    class X {
      public:
        typedef std::list<int> Container;
    
        Container m_container;
    };
    

    but that makes your class X obsolete.

    Other then that, if you really like your class, then add next methods :

    Container::const_iterator ElementBegin() const;
    Container::const_iterator ElementEnd() const;
    int size() const;
    
    0 讨论(0)
  • 2021-01-13 03:25

    I would use these names instead : iterator, const_iterator, begin, end, cbegin, cend and size() as:

    class X 
    {
      public :
    
        typedef std::list<int>::iterator iterator;
        typedef std::list<int>::const_iterator const_iterator ;
    
        iterator begin() { return m_container.begin(); }
        iterator end() { return m_container.end(); }
    
        const_iterator cbegin() const { return m_container.begin(); }
        const_iterator cend() const { return m_container.end(); }
    
        size_t size() const { return m_container.size(); }
    
      private :
        std::list<int> m_container;
    };
    

    And if you can use C++0x, then use m_container.cbegin() and m_container.cend() as:

    const_iterator cbegin() const { return m_container.cbegin(); }
    const_iterator cend() const { return m_container.cend(); }
    
    0 讨论(0)
  • 2021-01-13 03:28

    A mix of (2) and (3) would probably be what I'd do :

    class X {
      public :
        typedef std::list<int> ElementContainer;
        typedef ElementContainer::size_type ElementSizeType;
        typedef ElementContainer::iterator ElementIterator;
        typedef ElementContainer::const_iterator ConstElementIterator;
    
        ElementIterator elementBegin() { return m_container.begin(); }
        ElementIterator elementEnd() { return m_container.end(); }
    
        ConstElementIterator elementBegin() const { return m_container.begin(); }
        ConstElementIterator elementEnd() const { return m_container.end(); }
    
        ElementSizeType elementSize() const { return m_container.size(); }
    
      private :
        ElementContainer m_container;
    };
    

    It still leaves room to write custom iterators (by changing the typedefs), but as long as the ones provided by the container are ok, they can be used.

    0 讨论(0)
  • 2021-01-13 03:36

    2 and 3 really aren't distinct options. However, 3 as written is pretty much useless. No STL algorithm will use CustomIterator::next. For STL compatibility, you'd write:

    // mix of 2 and 3
    CustomIterator begin();
    CustomIterator end();
    

    and give CustomIterator the standard operator++ and operator*

    0 讨论(0)
  • 2021-01-13 03:40

    I can't think of much cleaner methods; you might consider the lightweight (4) solution giving access with

    const Container& container() const { return m_container; }
    

    I would prefer (3) since the container type becomes fully encapsulated, i.e. your type does not necessarily require inclusion of and you can change the container type without recompiling depending modules.

    0 讨论(0)
提交回复
热议问题