2015-09-26 24 views
1

考慮下面的代碼:的boost :: iterator_facade運營商 - >()編譯失敗

#include <boost/iterator/iterator_facade.hpp> 
#include <map> 


    // Class implements an stl compliant iterator to access the "sections" stored within a configuration. 
    template < typename _Iterator, typename _Reference > 
     class Section 
     : public boost::iterator_facade< 
        Section< _Iterator, _Reference >, 
        _Iterator, 
        boost::random_access_traversal_tag, 
        _Reference 
       > 
     { 
     private: 
      // Define the type of the base class: 
      typedef boost::iterator_facade< 
       Section< _Iterator, _Reference >, 
       _Iterator, 
       boost::random_access_traversal_tag, 
       _Reference 
      > base_type; 

     public: 
      // The following type definitions are common public typedefs: 
      typedef Section< _Iterator, _Reference > this_type; 
      typedef typename base_type::difference_type difference_type; 
      typedef typename base_type::reference  reference; 
      typedef _Iterator       iterator_type; 

     public: 
      explicit Section(const iterator_type it) 
      : m_it(it) 
      { } 

      // Copy constructor required to construct a const_iterator from an iterator: 
      template < typename _U > 
       Section(const Section< _U, _Reference > it) 
       : m_it(it.m_it) 
       { } 

     private: 
      // The following classes are friend of this class to ensure access onto the private member: 
                   friend class boost::iterator_core_access; 
      template < typename _Iterator, typename _Reference > friend class Section; 

      void increment(){ ++m_it; }               // Advance by one position. 
      void decrement(){ --m_it; }               // Retreat by one position. 
      void advance(const difference_type& n){ m_it += n };        // Advance by n positions. 
      bool equal(const this_type& rhs) const{ return m_it == rhs.m_it; }     // Compare for equality with rhs. 
      reference dereference() const { return m_it->second; }        // Access the value referred to. 
      difference_type distance_to(const this_type& rhs) const{ return rhs.m_it - m_it; } // Measure the distance to rhs. 

     private: 
      // Current "section" iterator: 
      iterator_type m_it; 
     }; 


struct Data 
{ 
    void f() const 
    { } 
}; 

typedef std::map< int, Data > map_type; 

typedef Section< const map_type::const_iterator, const Data& > iterator_type; 

map_type g_map; 

iterator_type begin() 
{ 
    return iterator_type(g_map.begin()); 
} 

void main() 
{ 
    iterator_type i = begin(); 

    // i->f(); // <--- error C2039: 'f' : is not a member of 'std::_Tree_const_iterator<_Mytree>' 
    (*i).f(); 
} 

所以迭代器的外觀應返回的數據類型的引用。這在調用解引用操作符時很好,但在調用operator - >()時編譯失敗。所以我有點困惑,因爲operator - >()試圖返回一個std :: map :: iterator。有任何想法嗎 ?

回答

1

迭代器對解除引用返回一個迭代器。要獲得f部分,您需要解除引用兩次。

看起來很像你誤解了iterator_facade模板參數的含義。第二個參數是而不是應該是任何迭代器類型(這是什麼導致你所有的麻煩)。相反,你應該用它來命名value_type

從您指定的dereference操作(和Ref),並希望在main(i->f())使用它的方式,它看起來像你只是想遍歷地圖的價值觀。所以,我會用更具描述性的名稱,以及重寫了整個事情,在這裏它,工作:

Live On Coliru

#include <boost/iterator/iterator_facade.hpp> 
#include <map> 

// Class implements an stl compliant iterator to access the "sections" stored within a configuration. 
template <typename Map, typename Value = typename Map::mapped_type> 
class MapValueIterator : public boost::iterator_facade<MapValueIterator<Map>, Value, boost::random_access_traversal_tag, Value const&> { 
    private: 
    // Define the type of the base class: 
    typedef Value const& Ref; 
    typedef boost::iterator_facade<MapValueIterator<Map>, Value, boost::random_access_traversal_tag, Ref> base_type; 

    public: 
    // The following type definitions are common public typedefs: 
    typedef MapValueIterator<Map> this_type; 
    typedef typename base_type::difference_type difference_type; 
    typedef typename base_type::reference reference; 
    typedef typename Map::const_iterator iterator_type; 

    public: 
    explicit MapValueIterator(const iterator_type it) : m_it(it) {} 

    // Copy constructor required to construct a const_iterator from an iterator: 
    template <typename U, typename V> MapValueIterator(const MapValueIterator<U,V> it) : m_it(it.m_it) {} 

    private: 
    // The following classes are friend of this class to ensure access onto the private member: 
    friend class boost::iterator_core_access; 
    template <typename U, typename V> friend class MapValueIterator; 

    void increment()          { std::advance(m_it);  } // Advance by one position. 
    void decrement()          { std::advance(m_it, -1); } // Retreat by one position. 
    void advance(const difference_type &n)     { std::advance(m_it, n); } // Advance by n positions. 
    bool equal(const this_type &rhs) const     { return m_it == rhs.m_it; } // Compare for equality with rhs. 
    reference dereference() const       { return m_it->second;  } // Access the value referred to. 
    difference_type distance_to(const this_type &rhs) const { return rhs.m_it - m_it; } // Measure the distance to rhs. 

    private: 
    // Current iterator: 
    iterator_type m_it; 
}; 

#include <iostream> 

struct Data { 
    void f() const { 
     std::cout << __PRETTY_FUNCTION__ << "\n"; 
    } 
}; 

typedef std::map<int, Data> map_type; 

template <typename Map> 
MapValueIterator<Map> map_value_iterator(Map const& m) { 
    return MapValueIterator<Map>(m.begin()); 
} 


int main() { 
    map_type g_map; 
    auto i = map_value_iterator(g_map); 

    i->f(); 
} 

它打印輸出

void Data::f() const 

正如你所期望的那樣。

請注意,有很多地方使用標準庫工具實現了成員函數。還要注意,迭代器「模仿」隨機訪問,但它不會具有預期的性能特徵(增量爲O(n))。

最後說明:我建議不要使用隱式轉換構造函數。我想你可以沒有它。


¹參考型通常應該是相同的(但裁判資格),除了在極少數情況下,你實際上是「代理」的價值觀。這是一個高級話題,很少應該使用。

+0

再次是一個很好的答案。非常感謝。是的,這是一個誤解如何使用值參數。現在它按預期工作! – Mark