How to provide stl as a container with an open iterator const and a private inert iterator?

I have a class that includes std :: list and wants to provide public begin () and end () for const_iterator and private begin () and end () for a simple iterator.

However, the compiler sees the closed version and complains that it is private rather than using the public version of const.

I understand that C ++ will not overload the return type (in this case const_iterator and iterator), and therefore it selects a non-constant version, since my object is not const.

Does my object end with const before calling begin () or does not overload the beginning of the name, is there any way to accomplish this?

I would think that this is a well-known pattern that people decided before, and would like to follow his example, as it is usually solved.

class myObject { public: void doSomethingConst() const; }; class myContainer { public: typedef std::list<myObject>::const_iterator const_iterator; private: typedef std::list<myObject>::iterator iterator; public: const_iterator begin() const { return _data.begin(); } const_iterator end() const { return _data.end(); } void reorder(); private: iterator begin() { return _data.begin(); } iterator end() { return _data.end(); } private: std::list<myObject> _data; }; void myFunction(myContainer &container) { myContainer::const_iterator itr = container.begin(); myContainer::const_iterator endItr = container.end(); for (; itr != endItr; ++itr) { const myObject &item = *itr; item.doSomethingConst(); } container.reorder(); // Do something non-const on container itself. } 

A compiler error looks something like this:

 ../../src/example.h:447: error: `std::_List_iterator<myObject> myContainer::begin()' is private caller.cpp:2393: error: within this context ../../src/example.h:450: error: `std::_List_iterator<myObject> myContainer::end()' is private caller.cpp:2394: error: within this context 

Thanks.

-William

+7
c ++ iterator stl const function-overloading
source share
4 answers

I think your only option is to rename private methods (if you need it first).

In addition, I believe that you should rename typedefs:

 class MyContainer { public: typedef std::list<Object>::const_iterator iterator; typedef iterator const_iterator; const_iterator begin() const; const_iterator end() const; private: typedef std::list<Object>::iterator _iterator; _iterator _begin(); _iterator _end(); ... }; 

Containers should print both iterator and const_iterator . A generic function that accepts a non-constant instance of your container can rely on the use of an iterator typedef - even if it is not going to change the elements. (For example, BOOST_FOREACH .)

It will be good if incorrect correctness is corrected, because if the general function is really trying to change the objects, the real type of the iterator (being const_iterator ) will not allow it.

As a test, the following compilation with your container:

 int main() { myContainer m; BOOST_FOREACH(const myObject& o, m) {} } 

Note that m is not a constant, but we are trying to get const references only to contained types, so this should be allowed.

+4
source share

Bad idea to get from std :: list (it is not intended for output).

Use a member variable of type std :: list.

 class myContainer { std::list<myObject> m_data; public: typedef std::list<myObject>::const_iterator myContainer::const_iterator; private: typedef std::list<myObject>::iterator myContainer::iterator; public: myContainer::const_iterator begin() const { return m_data.begin(); } myContainer::const_iterator end() const { return m_data.end(); } private: myContainer::iterator begin() { return m_data.begin(); } myContainer::iterator end() { return m_data.end(); } }; 
+5
source share

You need to change the name of the private start end. The compiler cannot distinguish only the return type

This works for me: pay attention to _begin _end names

 #include <list> class myObject {}; class myContainer : private std::list<myObject> { public: typedef std::list<myObject>::const_iterator const_iterator; private: typedef std::list<myObject>::iterator iterator; public: myContainer::const_iterator begin() const { return std::list<myObject>::begin(); } myContainer::const_iterator end() const { return std::list<myObject>::end(); } private: myContainer::iterator _begin() { return std::list<myObject>::begin(); } myContainer::iterator _end() { return std::list<myObject>::end(); } }; void myFunction(myContainer &container) { myContainer::const_iterator aItr = container.begin(); myContainer::const_iterator aEndItr = container.end(); for (; aItr != aEndItr; ++aItr) { const myObject &item = *aItr; // Do something const on container contents. } } int main(){ myContainer m; myFunction(m); } 
+4
source share

You might want to change the signature of your Myfunction method to this:

 void myFunction(const myContainer &container) 

because the const method will only be called on the const object. What is currently happening is that you are trying to call the non-const method, which in your case is private.

+1
source share

All Articles