0

背景
带有一堆代码的大型应用程序,我无法更改存储机制。

我想在存储在并行数组中的一组多维数据上创建一个迭代器,这样我们就可以开始使用标准算法和容器。

关于如何使其正常工作的任何想法?

#include <boost/iterator/iterator_facade.hpp>

#include <iostream>
#include <algorithm>

class curve_point_iterator;

const int curve_size = 10;

class curve
{
public:
  curve()
  {
    std::fill( x, &x[curve_size], 0.0 );
    std::fill( y, &y[curve_size], 0.0 );
  }

  double x[curve_size];
  double y[curve_size];

  curve_point_iterator begin();
  curve_point_iterator end();
};

class point_reference
{
public:
  point_reference( double& x_, double& y_ )
    : x( x_ )
    , y( y_ )
  {
  }

  point_reference& operator = ( point_reference& other )
  {
    x = other.x;
    y = other.y;

    return *this;
  }

  double & x;
  double & y;
};

class curve_point_iterator 
  : public boost::iterator_facade< 
          curve_point_iterator
        , point_reference
        , boost::random_access_traversal_tag >
{
public:
  curve_point_iterator()
    : index(0)
    , curve_(nullptr)
  {}

  explicit curve_point_iterator( curve* curve_in, size_t index_ = 0 )
    : index( index_ )
    , curve_( curve_in )
  {}

private:
  friend class boost::iterator_core_access;

  void increment()
  {
    ++index;
  }

  void decrement()
  {
    --index;
  }

  void advance( size_t n )
  {
    index += n;
  }

  difference_type distance_to( curve_point_iterator const& other ) const
  {
    return other.index - this->index;
  }

  bool equal(curve_point_iterator const& other) const
  {
      return this->index == other.index && this->curve_ == other.curve_;
  }

  point_reference& dereference() const
  {
    auto pt_ref = new( point_reference_buffer ) point_reference(  curve_->x[index]
                                                                , curve_->y[index] );
    return *pt_ref;
  }

  size_t index;
  mutable char point_reference_buffer[sizeof(point_reference)];
  curve* curve_;
};


curve_point_iterator curve::begin()
{
  return curve_point_iterator( this );
}

curve_point_iterator curve::end()
{
  return curve_point_iterator( this, curve_size+1 );
}


int main(int argc, char* argv[])
{
  curve crv;

  crv.x[1] = 20;
  crv.x[2] = 10;

  std::sort( crv.begin(), crv.end(), []( point_reference const& a, point_reference const& b )
  {
    return a.x < b.x;
  });

  for( auto i = 0; i < curve_size; ++i )
  {
    std::cout << crv.x[i] << std::endl;
  }

  return 0;
}

输出
0
20
20
20
20
20
20
20
20
20

改成之后

class point_reference
{
  ... ( all the other stuff )
  double x; // no longer reference
  double y; // no longer reference
};

输出
0
20
10
0
0
0
0
0
0

4

1 回答 1

0

好的,您需要做的是在point_reference之外引入一个点类型(具有值语义),它具有您正在寻找的引用语义。您需要值语义,以便交换等操作符合标准的预期。您可以使用第四个参数iterator_facade来允许这样做。此外,这种方式不需要使用可变缓冲区,因为 point_reference 本身是按值返回的。

此外,您curve::end()使用了错误的索引,应该使用curve_size它作为它的索引。

#include <boost/iterator/iterator_facade.hpp>

#include <iostream>
#include <algorithm>

class curve_point_iterator;

const int curve_size = 10;

class curve
{
public:
  curve()
  {
    std::fill( x, &x[curve_size], 0.0 );
    std::fill( y, &y[curve_size], 0.0 );
  }

  double x[curve_size];
  double y[curve_size];

  curve_point_iterator begin();
  curve_point_iterator end();
};

class point
{
public:
  point( const double& x_, const double& y_ )
    : x( x_ )
    , y( y_ )
  {
  }

  double x;
  double y;
};


class point_reference
{
public:
  point_reference( double& x_, double& y_ )
    : x( x_ ),
      y( y_ )
  {
  }

  point_reference& operator = ( const point& other )
  {
    x = other.x;
    y = other.y;

    return *this;
  }

  operator point() const
  {
    return point(x, y);
  }

  double & x;
  double & y;

  point_reference& operator=(const point_reference& other)
  {
    x = other.x;
    y = other.y;
  }

  point_reference* operator->()
  {
     return this;
  }

  point_reference* operator->() const
  {
     return this;
  }


};

class curve_point_iterator 
  : public boost::iterator_facade< 
          curve_point_iterator
  , point
  , boost::random_access_traversal_tag
  , point_reference>
{
public:
  curve_point_iterator()
    : index(0)
    , curve_(nullptr)
  {}

  explicit curve_point_iterator( curve* curve_in, size_t index_ = 0 )
    : index( index_ )
    , curve_( curve_in )
  {}

  point_reference operator->() const
  {
     return dereference();
  }

private:
  friend class boost::iterator_core_access;

  void increment()
  {
    ++index;
  }

  void decrement()
  {
    --index;
  }

  void advance( size_t n )
  {
    index += n;
  }

  difference_type distance_to( curve_point_iterator const& other ) const
  {
    return other.index - this->index;
  }

  bool equal(curve_point_iterator const& other) const
  {
    return this->index == other.index && this->curve_ == other.curve_;
  }

  point_reference dereference() const
  {
    //    auto pt_ref = new( point_reference_buffer ) point_reference(  curve_->x[index]
    //                                , curve_->y[index] );
    //    return *pt_ref;
    return point_reference(curve_->x[index], curve_->y[index]);
  }

  size_t index;
  curve* curve_;
};


curve_point_iterator curve::begin()
{
  return curve_point_iterator( this );
}

curve_point_iterator curve::end()
{
  return curve_point_iterator( this, curve_size );
}


int main(int argc, char* argv[])
{
  curve crv;

  crv.x[1] = 20;
  crv.x[2] = 10;

  std::sort( crv.begin(), crv.end(), []( point const& a, point const& b )
         {
           return a.x < b.x;
         });

  for( auto i = 0; i < curve_size; ++i )
    {
      std::cout << crv.x[i] << std::endl;
    }

  return 0;
}

输出:

0
0
0
0
0
0
0
0
10
20
于 2012-06-21T12:01:24.533 回答