const context iterator
Jul 4, 2014 at 8:36am UTC
Hi everyone,
I have a data class that I use in 2 ways: To save data, in which case other classes have access and can modify content, and to read data, in which case other classes only get to read data.
For this, I have some doubly defined methods, like:
1 2
const DataNode* GetChild(const std::string& name) const ;
DataNode* GetChild(const std::string& name);
Now, I also have iterators, that allows iteration over the internal data map:
1 2 3 4
const std::multimap<const std::string, DataNode*>::const_iterator Begin() const ;
const std::multimap<const std::string, DataNode*>::iterator Begin();
const std::multimap<const std::string, DataNode*>::const_iterator End() const ;
const std::multimap<const std::string, DataNode*>::iterator End();
Data is stored here:
std::multimap<const std::string, DataNode*> children_;
Now here's the problem: I don't want classes to be able to modify children from a const context, so really, I want the const iterators to be of the type
1 2
const std::multimap<const std::string, const DataNode*>::const_iterator Begin() const ;
const std::multimap<const std::string, const DataNode*>::const_iterator End() const ;
But I don't know how I could return this type. Is it possible without having to have another multimap?
Jul 4, 2014 at 10:44am UTC
boost::transform_iterator can generate the boiler-plate code.
http://www.boost.org/doc/libs/1_55_0/libs/iterator/doc/transform_iterator.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
#include <iostream>
#include <map>
#include <boost/iterator/transform_iterator.hpp>
#include <type_traits>
struct data_class
{
struct DataNode { /* ... */ };
using iterator = std::multimap< /*const*/ std::string, DataNode* >::iterator ;
using citerator = std::multimap< /*const*/ std::string, DataNode* >::const_iterator ;
iterator begin() { return children_.begin() ; }
iterator end() { return children_.end() ; }
struct add_const
{
std::pair< const std::string, const DataNode* > operator ()
( const std::pair< const std::string, DataNode* >& p ) const { return p ; }
};
using const_iterator = boost::transform_iterator< add_const, citerator > ;
const_iterator begin() const
{ return boost::make_transform_iterator( children_.cbegin(), add_const() ) ; }
const_iterator end() const
{ return boost::make_transform_iterator( children_.cend(), add_const() ) ; }
private : std::multimap< /*const*/ std::string, DataNode* > children_ ;
};
int main()
{
data_class dc ;
static_assert ( std::is_same< decltype ( dc.begin()->second ), data_class::DataNode* >::value, "****" ) ;
const data_class& cdc = dc ;
static_assert ( std::is_same< decltype ( cdc.begin()->second ), const data_class::DataNode* >::value, "****" ) ;
}
http://coliru.stacked-crooked.com/a/2ff80da19284b623
Last edited on Jul 4, 2014 at 11:02am UTC
Jul 4, 2014 at 11:29am UTC
I'll try this, thanks!
Topic archived. No new replies allowed.