0

テンプレート化されたビジターを使用していくつかのクラスの統一されたインターフェイスを定義しています。__str__メソッドとメソッドを定義する目的で、オブジェクトからクラス名 (参照ドキュメント内の)__repr__をプログラムで取得したいと考えています。それは可能ですか?"X"boost::python::class

クラス名を引数としてビジターのコンストラクターに渡すことで簡単に回避できますが、自動的にクラス名を指定する方がエレガントです。

4

1 に答える 1

5

boost::python::class_から派生しているため、クラス オブジェクトから属性boost::python::objectを照会できます。__name__

簡単な例を次に示します。

#include <boost/python.hpp>

class X {};

BOOST_PYTHON_MODULE(example)
{ 
  namespace python = boost::python;
  python::object x_class = python::class_<X>("X");

  // Extract the class' __name__ attribute, printing whatever was passed to
  // class_ constructor.
  std::cout << boost::python::extract<std::string>(x_class.attr("__name__"))()
            << std::endl;
}

そして出力:

>>> import example
X

このアプローチを拡張するには、派生元の訪問者は次のboost::python::def_visitorいずれかを行う必要があります。

  • __str__and/orをを介して「クラス」名を__repr__一般的に返す関数として定義 します。boost::python::objecto.__class__.__name__
  • クラス名を抽出して保存し 、保存された値にアクセスする関数として__str__and/orを定義します。__repr__

次の例は、これらのアプローチの両方を示しています。

#include <boost/python.hpp>

/// @brief Helper type used to set and get a boost::python::class_
///        object's type name.
template <typename ClassT>
class typed_class_name
{
public:
  /// @brief Extract and store the __name__ from a 
  ///        boost::python::class_ objct.
  static void set(const ClassT& c)
  {
    name_ = boost::python::extract<std::string>(c.attr("__name__"));
  }

  /// @brief Return the stored name.
  static std::string get(const typename ClassT::wrapped_type&)
  {
    std::cout << "typed" << std::endl;
    return name_;
  }
private:
  static std::string name_;
};

template <typename ClassT> std::string typed_class_name<ClassT>::name_;

/// @brief Generically get a python object's class name. 
struct generic_class_name
{
  static boost::python::object get(const boost::python::object& self)
  {
    std::cout << "generic" << std::endl;
    return self.attr("__class__").attr("__name__");
  }
};

class my_def_visitor
  : public boost::python::def_visitor<my_def_visitor>
{
  friend class boost::python::def_visitor_access;

  template <class ClassT>
  void visit(ClassT& c) const
  {
    // Store the class name.
    typed_class_name<ClassT>::set(c);

    c 
      .def("__str__",  &typed_class_name<ClassT>::get) // typed
      .def("__repr__", &generic_class_name::get)       // generic
      ;
  }
};

class X {};

BOOST_PYTHON_MODULE(example)
{ 
  namespace python = boost::python;
  python::class_<X>("X")
    .def(my_def_visitor())
    ;
}

そして使用法:

>>> import example
>>> x = example.X()
>>> str(x)
typed
'X'
>>> repr(x)
generic
'X'
于 2013-07-31T16:22:20.177 に答える