【问题标题】:Simplify generating wrapper classes in Pybind11 for a C++ template class: a template declaration cannot appear at block scope简化在 Pybind11 中为 C++ 模板类生成包装类:模板声明不能出现在块范围内
【发布时间】:2020-05-13 15:34:19
【问题描述】:

我正在尝试简化在 Pybind11 中为 C++ 模板类生成包装类。这是一个显示问题的最小示例(遵循this 答案):

#include <pybind11/pybind11.h>
#include <iostream>

namespace py = pybind11;

template<class T>
class Foo {
public:
    Foo(T bar) : bar_(bar) {}
    void print() {
        std::cout << "Type id: " << typeid(T).name() << '\n';
    }
private:
    T bar_;
};

PYBIND11_MODULE(example, m) {
    template<typename T>
    void declare_foo(py::module &m, std::string &typestr) {
        using Class = Foo<T>;
        std::string pyclass_name = std::string("Foo") + typestr;
        py::class_<Class>(m, pyclass_name.c_str())
            .def(py::init< T >())
            .def("print", &Class::print);
    }
    declare_foo<int>(m, "Int");
    declare_foo<double>(m, "Double");
    # More similar declarations follow here...
}

当我编译这个时:

g++ -O3 -Wall -shared -std=c++17 -fPIC `python3 -m pybind11 --includes` example.cpp -o example`python3-config --extension-suffix`

我得到错误:

example.cpp: In function ‘void pybind11_init_example(pybind11::module&)’:
example.cpp:18:5: error: a template declaration cannot appear at block scope
   18 |     template<typename T>
      |     ^~~~~~~~

【问题讨论】:

    标签: python c++ pybind11


    【解决方案1】:

    就像错误暗示你不能在块范围内有一个模板声明(你显然在一个https://en.cppreference.com/w/cpp/language/scope中)。只需将其移出并通过 const 引用(或值)捕获字符串参数。

    把代码改成

    template<typename T>
    void declare_foo(py::module &m, const std::string &typestr) {
        using Class = Foo<T>;
        std::string pyclass_name = std::string("Foo") + typestr;
        py::class_<Class>(m, pyclass_name.c_str())
            .def(py::init< T >())
            .def("print", &Class::print);
    }
    
    PYBIND11_MODULE(example, m) {
        declare_foo<int>(m, "Int");
        declare_foo<double>(m, "Double");
    }
    

    有效。

    附带说明一下,您还应该

    #include <string>
    

    不建议依赖传递包含。

    【讨论】:

      【解决方案2】:

      我想出了以下使用宏的解决方法

      template<class T>
      class Foo {
      public:
          Foo(T bar) : bar_(bar) {}
          void print() {
              std::cout << "Type id: " << typeid(T).name() << '\n';
          }
      private:
          T bar_;
      };
      
      #define DECLARE_FOO(T, NAME) { \
        py::class_<Foo<T> >(m, (std::string("Foo")+NAME).c_str()) \
          .def(py::init< T >()) \
          .def("print", &Foo<T>::print); \
      }
      
      PYBIND11_MODULE(example, m) {
        DECLARE_FOO(int, "int");
        DECLARE_FOO(float, "float");
      }
      

      它似乎可以工作,但是我不确定这个宏是否足够强大。

      【讨论】:

        猜你喜欢
        • 2020-09-07
        • 1970-01-01
        • 2015-07-05
        • 1970-01-01
        • 1970-01-01
        • 2017-02-09
        • 2011-01-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多