boost/python/iterator.hpp

はじめに

<boost/python/iterator.hpp> は、C++ のコンテナイテレータから Python のイテレータを作成するための型と関数を提供する。ある class_ がランダムアクセスイテレータをサポートする場合、この機能を使用するより __getitem__(シーケンスプロトコルともいう)を実装したほうがよい。Python は自動的にイテレータ型を作成し(iter() を見よ)、各アクセスは範囲チェックが行われ、不正な C++ イテレータを介してアクセスする可能性もない。

クラス

iterator クラステンプレート

template<class Container, class NextPolicies = unspecified>
struct iterator : object

iterator<C, P> のインスタンスは、呼び出し可能な Python オブジェクトへの参照を保持する。このオブジェクトは Python から呼び出され、C へ変換可能な単一の引数 c を受け取り、[c.begin(),c.end()) を走査する Python イテレータを作成する。省略可能な CallPolicies である P は、走査中に要素をどのように返すか制御するのに使用する。

以下の説明において、cContainer のインスタンスである。

テンプレートパラメータ
  • Container --

    結果はその引数を c に変換し、c.begin() および c.end() を呼び出しイテレータを得る。Containerconstbegin および end 関数を呼び出すには const でなければならない。

    要件

    [c.begin(),c.end()) が合法なイテレータ範囲である。

  • NextPolicies --

    結果のイテレータの next メソッドに適用される。

    要件

    CallPolicies のデフォルトコンストラクト可能なモデル。

    既定

    常に内部的な C++ イテレータを逆参照した結果のコピーを作成する、未規定の CallPolicies モデル。

iterator クラステンプレートの概要

namespace boost { namespace python
{
  template <class Container
             , class NextPolicies = unspecified>
  struct iterator : object
  {
      iterator();
  };
}}

iterator クラステンプレートのコンストラクタ

iterator()
効果

基底クラスを以下の結果で初期化する。

range<NextPolicies>(&iterators<Container>::begin, &iterators<Container>::end)
事後条件

this->get() は、上記のとおり Python のイテレータを作成する Python の呼び出し可能オブジェクトを指す。

根拠

ラップする C++ クラスが begin および end を持つようなありふれた場合について、イテレータを容易に作成する方法を提供する。

iterators クラステンプレート

template<class C>
struct iterators

引数の begin および end メンバ関数を確実に呼び出す方法を提供するユーティリティクラスである。C++ 標準ライブラリにおけるコンテナについて、メンバ関数のアドレスを取る移植可能な方法はないので、それらをラップする場合に iterators<> は特に有効である。

以下の表において、xC のインスタンスである。

要求する合法な式

x.begin()

Cconst な型であれば C::const_iterator へ変換可能。そうでなければ C::iterator へ変換可能。

x.end()

Cconst な型であれば C::const_iterator へ変換可能。そうでなければ C::iterator へ変換可能。

iterators クラステンプレートの概要

namespace boost { namespace python
{
  template <class C>
  struct iterators
  {
      typedef typename C::[const_]iterator iterator;
      static iterator begin(C& x);
      static iterator end(C& x);
  };
}}

iterators クラステンプレートの入れ子型

Cconst 型の場合、

typedef typename C::const_iterator iterator;

それ以外の場合、

typedef typename C::iterator iterator;

iterators クラステンプレートの静的関数

static iterator begin(C&)
戻り値

x.begin()

static iterator end(C&)
戻り値

x.end()

関数

template<class NextPolicies, class Target, class Accessor1, class Accessor2>
object range(Accessor1 start, Accessor2 finish)
template<class NextPolicies, class Accessor1, class Accessor2>
object range(Accessor1 start, Accessor2 finish)
template<class Accessor1, class Accessor2>
object range(Accessor1 start, Accessor2 finish)
要件

NextPolicies は、デフォルトコンストラクト可能な CallPolicies モデル。

効果

第 1 形式は Python の呼び出し可能オブジェクトを作成する。このオブジェクトは呼び出されるとその引数を Target オブジェクト x に変換し、[bind(start, _1)(x),bind(finish, _1)(x)) を走査する Python のイテレータを作成する。イテレータの next 関数には NextPolicies を適用する。第 2 形式は、以下のように Accessor1 から Target を推論する点以外は第 1 形式と同じである。

  • Accessor1 が関数型の場合、Target はその第 1 引数の型。

  • Accessor1 がデータメンバポインタ R (T::*) の場合、TargetT と同じ。

  • Accessor1 がメンバ関数ポインタ R (T::*)(arguments...) cv-optcv-opt は省略可能な cv-qualifier)の場合、TargetT と同じ。

第 3 形式は、NextPolicies が常に内部的な C++ イテレータを逆参照した結果のコピーを作成する CallPolicies の未規定のモデルであること以外は第 2 形式と同じである。

根拠

boost::bind() を使用することで、関数、メンバ関数、データメンバポインタを通じて C++ イテレータへアクセスできる。ラップしたクラス型のシーケンス要素のコピーが高コストな場合、NextPolicies のカスタマイズが有効である(例えば return_internal_reference を使用する)。Accessor1 が関数オブジェクトであるか、対象型の基底クラスが他から推論される場合は、Target のカスタマイズが有効である。

#include <boost/python/module.hpp>
#include <boost/python/class.hpp>

#include <vector>

using namespace boost::python;
BOOST_PYTHON_MODULE(demo)
{
    class_<std::vector<double> >("dvec")
        .def("__iter__", iterator<std::vector<double> >())
        ;
}

より包括的な例が以下にある。

  • http://www.boost.org/libs/python/test/iterator.cpp

  • http://www.boost.org/libs/python/test/input_iterator.cpp

  • http://www.boost.org/libs/python/test/input_iterator.py