Boost iterator_facade 取消引用

发布于 2024-12-06 11:27:01 字数 8427 浏览 1 评论 0原文

我正在尝试使用 boost 迭代器外观来为存储 data_t 类型元素的排序向量的类实现迭代器。目前我在取消引用它时遇到了麻烦。我只需要迭代器进行遍历和搜索,迭代器不需要更改 Range 对象的任何内部状态。

这是 range.hpp:

#include <algorithm>
#include <vector>
#include <sstream>
#include <stdexcept>
#include <functional>

#include <boost/iterator/iterator_facade.hpp>

struct testRangeImpl{
    typedef unsigned int data_t;

    struct RangeOrdering : public std::binary_function< data_t const &, data_t const &, bool >{
        bool operator()(data_t const& a, data_t const& b){
            return a < b;
        }
    };
};


template<
    typename ImplT 
>
class SortedRange: public boost::iterator_facade< 
                    SortedRange< ImplT >,  //this type because of the CRTP
                    typename ImplT::data_t, //The type of the data
                    boost::bidirectional_traversal_tag //iterators can be incremented and decremented
                >{
    public:
        /*! this type */
        typedef SortedRange< ImplT > type;

        /*! The type of the implementation policy */
        typedef ImplT impl_t; 

        /*! The internal representation of an element */
        typedef typename impl_t::data_t data_t;

        /*! The internal representation of a range */
        typedef std::vector< data_t > range_t;

        /*! A member variabe to keep track of if the range has been sorted */
        bool m_sorted;

        /*! The actual range itself in its internal representation */
        range_t m_range;

        /*! The actual range itself in its internal representation */
        size_t m_range_size;

        /*! An exception indicating an invalid range */
        struct InvalidRangeException{};

        /*! Current element for iterator */
        size_t m_current_combo;

        enum class PositionClass {
            NOT_END,
            END,
            REND
        };

        explicit SortedRange( )
            : m_sorted(false), m_range(), m_range_size(0), m_current_combo(0) , m_posclass(PositionClass::END){
        }

        explicit SortedRange(std::vector < data_t > const& rg, size_t const& current_combo, PositionClass const& p )
            : m_sorted(false), m_range(rg), m_range_size(rg.size()), m_current_combo(current_combo) , m_posclass(p){
            if(rg.empty()){
                throw InvalidRangeException();
            }
            std::sort(m_range.begin(),m_range.end(),typename ImplT::RangeOrdering());
            m_sorted = true;
            //initialise();
        }

    protected:
        explicit SortedRange(std::vector < data_t > const& rg)
            : m_sorted(false), m_range(rg), m_range_size(rg.size()), m_current_combo(0) , m_posclass(PositionClass::NOT_END){
            if(rg.empty()){
                throw InvalidRangeException();
            }
            std::sort(m_range.begin(),m_range.end(),typename ImplT::RangeOrdering());
            m_sorted = true;
            //initialise();
        }   

        /*! Implementation policy object */
        impl_t m_impl;

        /*! construct a range with a specific internal state */
        explicit SortedRange(std::vector < data_t > const& rg, size_t const& current_combo)
            : m_sorted(false), m_range(rg), m_range_size(rg.size()), m_current_combo(current_combo) , m_posclass(PositionClass::NOT_END){
            if(rg.empty()){
                throw InvalidRangeException();
            }
            std::sort(m_range.begin(),m_range.end(),typename ImplT::RangeOrdering());
            m_sorted = true;
            //initialise();
        }
    public:

        size_t size(){
            m_range_size = m_range.size();
            return m_range_size;
        }

        /* Return first data */
        type begin() const {
            return type(m_range, 0);
        }

        type end() const {
            return type(m_range, m_current_combo, PositionClass::END);
        }

        type rend() const {
            return type(m_range, m_current_combo, PositionClass::REND);
        }

        /* Return last data */
        type rbegin() const {
            return type(m_range, m_range_size -1 );
        }

    private:
        friend class boost::iterator_core_access;

        /*! Position class */
        PositionClass m_posclass;

        /*! set up the initial state */
        void initialise() {
            std::sort(m_range.begin(),m_range.end());
            m_sorted == true;
        }

        /*! the first element */
        data_t first() const {
            return m_range[0];
        }

        /*! the last element */
        data_t last() const {
            return m_range[m_range_size - 1];
        }


        /*! return the current element */
        const data_t& dereference() const  {
            if(m_posclass == PositionClass::NOT_END) {
                return m_range[m_current_combo];
            }else {
                throw std::out_of_range("Attempt to dereference past the valid range");
            }
        }

        /*! get the next combination */
        void increment() {
            if(m_posclass != PositionClass::NOT_END)
                throw std::out_of_range("Cannot increment past the valid range");

            if(m_current_combo == m_range_size ) {
                //current combination is the last
                m_posclass = PositionClass::END;
            }
            m_current_combo++;
        }

        /*! get the previous combination */
        void decrement() {
            if(m_posclass != PositionClass::NOT_END)
                throw std::out_of_range("Cannot decrement past the valid range");

            if(m_current_combo == 0) {
                //current combination is the first
                m_posclass = PositionClass::REND;
            }
            m_current_combo--;  
        }

        /*! check for equality between two iterators. */
        bool equal(type const& other) const {
           if(m_posclass == PositionClass::NOT_END && 
           other.m_posclass == PositionClass::NOT_END) {

               return 
                   m_current_combo == other.m_current_combo &&
                   m_range == other.m_range;
           }
           else {
                return m_posclass == other.m_posclass && m_range == other.m_range;
           }
        }
};

struct Range : public SortedRange< testRangeImpl>{
    /*! An exception we throw if someone tries to construct an invalid range */
    struct InvalidRangeException : public SortedRange< testRangeImpl >::InvalidRangeException {};

    /*! Construct a range from a vector of unsigned ints */
    explicit Range(std::vector<unsigned int> const& r) : SortedRange<testRangeImpl>(r)
    {
        if(r.empty()){
            throw InvalidRangeException();
        }
    }
};

这是 main.cpp:

#include <vector>
#include <iostream>
#include "range.hpp"
int main(void){
    std::vector<unsigned int> rg  = { 2 , 5 , 1 , 3 , 4 };
    Range test(rg);
    for(auto elem: test){
        std::cout << elem << " " ;
    }
    return 0;
}

编译出现此错误:

/usr/include/boost/iterator/iterator_facade.hpp: In static member function ‘static typename Facade::reference boost::iterator_core_access::dereference(const Facade&) [with Facade = SortedRange<testRangeImpl>, typename Facade::reference = unsigned int&]’:
/usr/include/boost/iterator/iterator_facade.hpp:643:67:   instantiated from ‘boost::iterator_facade<I, V, TC, R, D>::reference boost::iterator_facade<I, V, TC, R, D>::operator*() const [with Derived = SortedRange<testRangeImpl>, Value = unsigned int, CategoryOrTraversal = boost::bidirectional_traversal_tag, Reference = unsigned int&, Difference = long int, boost::iterator_facade<I, V, TC, R, D>::reference = unsigned int&]’
main.cpp:9:17:   instantiated from here
/usr/include/boost/iterator/iterator_facade.hpp:517:32: error: invalid initialisation of reference of type ‘boost::iterator_facade<SortedRange<testRangeImpl>, unsigned int, boost::bidirectional_traversal_tag, unsigned int&, long int>::reference {aka unsigned int&}’ from expression of type ‘const data_t {aka const unsigned int}’

如何使其成为可用的迭代器类型?

I'm trying to use boost iterator facade to implement an iterator for a class that stores a sorted vector of elements of type data_t. Currently I'm having troubles with dereferencing it. I only need the iterator for traversal and searching, the iterator doesn't need to change any of the internal state of the Range object.

Here's the range.hpp:

#include <algorithm>
#include <vector>
#include <sstream>
#include <stdexcept>
#include <functional>

#include <boost/iterator/iterator_facade.hpp>

struct testRangeImpl{
    typedef unsigned int data_t;

    struct RangeOrdering : public std::binary_function< data_t const &, data_t const &, bool >{
        bool operator()(data_t const& a, data_t const& b){
            return a < b;
        }
    };
};


template<
    typename ImplT 
>
class SortedRange: public boost::iterator_facade< 
                    SortedRange< ImplT >,  //this type because of the CRTP
                    typename ImplT::data_t, //The type of the data
                    boost::bidirectional_traversal_tag //iterators can be incremented and decremented
                >{
    public:
        /*! this type */
        typedef SortedRange< ImplT > type;

        /*! The type of the implementation policy */
        typedef ImplT impl_t; 

        /*! The internal representation of an element */
        typedef typename impl_t::data_t data_t;

        /*! The internal representation of a range */
        typedef std::vector< data_t > range_t;

        /*! A member variabe to keep track of if the range has been sorted */
        bool m_sorted;

        /*! The actual range itself in its internal representation */
        range_t m_range;

        /*! The actual range itself in its internal representation */
        size_t m_range_size;

        /*! An exception indicating an invalid range */
        struct InvalidRangeException{};

        /*! Current element for iterator */
        size_t m_current_combo;

        enum class PositionClass {
            NOT_END,
            END,
            REND
        };

        explicit SortedRange( )
            : m_sorted(false), m_range(), m_range_size(0), m_current_combo(0) , m_posclass(PositionClass::END){
        }

        explicit SortedRange(std::vector < data_t > const& rg, size_t const& current_combo, PositionClass const& p )
            : m_sorted(false), m_range(rg), m_range_size(rg.size()), m_current_combo(current_combo) , m_posclass(p){
            if(rg.empty()){
                throw InvalidRangeException();
            }
            std::sort(m_range.begin(),m_range.end(),typename ImplT::RangeOrdering());
            m_sorted = true;
            //initialise();
        }

    protected:
        explicit SortedRange(std::vector < data_t > const& rg)
            : m_sorted(false), m_range(rg), m_range_size(rg.size()), m_current_combo(0) , m_posclass(PositionClass::NOT_END){
            if(rg.empty()){
                throw InvalidRangeException();
            }
            std::sort(m_range.begin(),m_range.end(),typename ImplT::RangeOrdering());
            m_sorted = true;
            //initialise();
        }   

        /*! Implementation policy object */
        impl_t m_impl;

        /*! construct a range with a specific internal state */
        explicit SortedRange(std::vector < data_t > const& rg, size_t const& current_combo)
            : m_sorted(false), m_range(rg), m_range_size(rg.size()), m_current_combo(current_combo) , m_posclass(PositionClass::NOT_END){
            if(rg.empty()){
                throw InvalidRangeException();
            }
            std::sort(m_range.begin(),m_range.end(),typename ImplT::RangeOrdering());
            m_sorted = true;
            //initialise();
        }
    public:

        size_t size(){
            m_range_size = m_range.size();
            return m_range_size;
        }

        /* Return first data */
        type begin() const {
            return type(m_range, 0);
        }

        type end() const {
            return type(m_range, m_current_combo, PositionClass::END);
        }

        type rend() const {
            return type(m_range, m_current_combo, PositionClass::REND);
        }

        /* Return last data */
        type rbegin() const {
            return type(m_range, m_range_size -1 );
        }

    private:
        friend class boost::iterator_core_access;

        /*! Position class */
        PositionClass m_posclass;

        /*! set up the initial state */
        void initialise() {
            std::sort(m_range.begin(),m_range.end());
            m_sorted == true;
        }

        /*! the first element */
        data_t first() const {
            return m_range[0];
        }

        /*! the last element */
        data_t last() const {
            return m_range[m_range_size - 1];
        }


        /*! return the current element */
        const data_t& dereference() const  {
            if(m_posclass == PositionClass::NOT_END) {
                return m_range[m_current_combo];
            }else {
                throw std::out_of_range("Attempt to dereference past the valid range");
            }
        }

        /*! get the next combination */
        void increment() {
            if(m_posclass != PositionClass::NOT_END)
                throw std::out_of_range("Cannot increment past the valid range");

            if(m_current_combo == m_range_size ) {
                //current combination is the last
                m_posclass = PositionClass::END;
            }
            m_current_combo++;
        }

        /*! get the previous combination */
        void decrement() {
            if(m_posclass != PositionClass::NOT_END)
                throw std::out_of_range("Cannot decrement past the valid range");

            if(m_current_combo == 0) {
                //current combination is the first
                m_posclass = PositionClass::REND;
            }
            m_current_combo--;  
        }

        /*! check for equality between two iterators. */
        bool equal(type const& other) const {
           if(m_posclass == PositionClass::NOT_END && 
           other.m_posclass == PositionClass::NOT_END) {

               return 
                   m_current_combo == other.m_current_combo &&
                   m_range == other.m_range;
           }
           else {
                return m_posclass == other.m_posclass && m_range == other.m_range;
           }
        }
};

struct Range : public SortedRange< testRangeImpl>{
    /*! An exception we throw if someone tries to construct an invalid range */
    struct InvalidRangeException : public SortedRange< testRangeImpl >::InvalidRangeException {};

    /*! Construct a range from a vector of unsigned ints */
    explicit Range(std::vector<unsigned int> const& r) : SortedRange<testRangeImpl>(r)
    {
        if(r.empty()){
            throw InvalidRangeException();
        }
    }
};

Here's the main.cpp:

#include <vector>
#include <iostream>
#include "range.hpp"
int main(void){
    std::vector<unsigned int> rg  = { 2 , 5 , 1 , 3 , 4 };
    Range test(rg);
    for(auto elem: test){
        std::cout << elem << " " ;
    }
    return 0;
}

Compiling gives this error:

/usr/include/boost/iterator/iterator_facade.hpp: In static member function ‘static typename Facade::reference boost::iterator_core_access::dereference(const Facade&) [with Facade = SortedRange<testRangeImpl>, typename Facade::reference = unsigned int&]’:
/usr/include/boost/iterator/iterator_facade.hpp:643:67:   instantiated from ‘boost::iterator_facade<I, V, TC, R, D>::reference boost::iterator_facade<I, V, TC, R, D>::operator*() const [with Derived = SortedRange<testRangeImpl>, Value = unsigned int, CategoryOrTraversal = boost::bidirectional_traversal_tag, Reference = unsigned int&, Difference = long int, boost::iterator_facade<I, V, TC, R, D>::reference = unsigned int&]’
main.cpp:9:17:   instantiated from here
/usr/include/boost/iterator/iterator_facade.hpp:517:32: error: invalid initialisation of reference of type ‘boost::iterator_facade<SortedRange<testRangeImpl>, unsigned int, boost::bidirectional_traversal_tag, unsigned int&, long int>::reference {aka unsigned int&}’ from expression of type ‘const data_t {aka const unsigned int}’

How do I get this to be a usable iterator type?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

诗化ㄋ丶相逢 2024-12-13 11:27:01

您正在尝试对 const 值进行非常量引用。由于某种原因,您决定取消引用返回常量引用,而不是遵循外观引用类型。解决这个问题,它应该可以工作。

You are trying to take a non-const reference to a const value. For some reason you have decided that dereference returns a const reference, instead of honoring the facade reference type. Fix that, and it should work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文