const context iterator

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?
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
I'll try this, thanks!
Registered users can post here. Sign in or register to post.