0

背景
コードのバンドルを含む大規模なアプリケーションで、ストレージメカニズムを変更できません。

stdアルゴリズムとコンテナーの使用を開始できるように、並列配列に格納されている一連の多次元データに対してイテレーターを作成したいと思います。

これを正しく機能させる方法について何かアイデアはありますか?

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

出力
02020
20
20
20
20
20
20
20
_
_

に変更した後

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

出力 02010
0 0 0 0 0 0
_ _






4

1 に答える 1

0

さて、あなたがする必要があるのは、あなたが探している参照セマンティクスを持つpoint_referenceに加えて、ポイントタイプ(値セマンティクスを持つ)を導入することです。スワップなどの操作が標準の期待どおりに機能するように、値のセマンティクスが必要です。の4番目の引数を使用し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 に答える