简体   繁体   English

boost :: iterator_facade运算符->()无法编译

[英]boost::iterator_facade operator->() fails to compile

Consider the following code: 考虑以下代码:

#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( );
}

So the iterator facade shall return a reference to Data type. 因此,迭代器外观必须返回对数据类型的引用。 This works well when dereference operator is called but compile fails when operator->() is called. 这在调用取消引用运算符时很好用,但是在调用operator->()时编译失败。 So I am a bit confused because operator->() tries to return a std::map::iterator. 所以我有点困惑,因为operator->()尝试返回std :: map :: iterator。 Any ideas ? 有任何想法吗 ?

The iterator returns an iterator on dereference. 迭代器在取消引用时返回迭代器。 To get the f part, you need to dereference twice. 要获得f部分,您需要取消引用两次。

It looks a lot like you misunderstood the meaning of the template arguments to iterator_facade . 看起来很像您误解了iterator_facade模板参数的含义。 The second argument is not supposed to be any iterator type (this is what causes all your trouble). 第二个参数不应为任何迭代器类型(这是导致您所有麻烦的原因)。 Instead you should use it to name your value_type 相反,您应该使用它来命名您的value_type

From the way you specified the dereference operation (and Ref ) and wanted to use it in main ( i->f() ) it looks like you just wanted to iterate the map's values. 从您指定dereference操作(和Ref )并想在main( i->f() )中使用它的方式来看,您似乎只是想迭代地图的值。 So, I'd rewrite the whole thing using more descriptive names as well, and here it is, working: 因此,我也将使用更具描述性的名称来重写整个过程,并且可以正常工作:

Live On Coliru 生活在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();
}

Which prints the output 哪个打印输出

void Data::f() const

as you'd expect. 如您所愿。

Note that there are numerous places where I implemented the member functions using standard library facilities. 请注意,在很多地方我都使用标准库工具来实现成员函数。 Note as well, the iterator "mimics" random access, but it won't have the expected performance characteristics (increment is O(n)). 还要注意,迭代器“模仿”随机访问,但不会具有预期的性能特征(增量为O(n))。

Final note: I'd recommend against having the implicit conversion constructor. 最后说明:建议不要使用隐式转换构造函数。 I think you can do without it. 我想你可以没有它。


¹ The reference-type should typically be the same (but ref-qualified) except in rare cases where you actually "proxy" the values. ¹除了在少数情况下实际“代理”值之外,引用类型通常应相同(但具有ref限定)。 This is an advanced topic and rarely should be used. 这是一个高级主题,很少使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM