【问题标题】:Pybind - Curiously Recurring TemplatePybind - 奇怪地重复出现的模板
【发布时间】:2018-06-27 08:44:44
【问题描述】:

我有以下类结构(我的实际实现的简化示例):

/* TestClass.hpp */
#pragma once

template <class Impl>
class CurRecTemplate {
protected:
    CurRecTemplate() {}
    ~CurRecTemplate() {}

    Impl& impl() { return static_cast<Impl&>(*this); }
    const Impl& impl() const { return static_cast<const Impl&>(*this); }
};

template <class Impl>
class BaseClass : public CurRecTemplate<Impl> {
public:
    BaseClass() { };

    template <class FuncType>
    double eval(const FuncType& func, double x) const
    {
        return this->impl().evalImplementation(func, x);
    }
};

class DerivedClass : public BaseClass<DerivedClass> {
public:
    template <class FuncType>
    double evalImplementation(const FuncType& f, double x) const
    {
        return f(x);
    };
};

然后

/* Source.cpp */
#include <pybind11/pybind11.h>
#include "TestClass.hpp"

namespace py = pybind11;

template<typename Impl>
void declare(py::module &m, const std::string& className) {
    using DeclareClass = BaseClass<Impl>;

    py::class_<DeclareClass, std::shared_ptr<DeclareClass>>(m, className.c_str())
        .def(py::init<>())
        .def("eval", &DeclareClass::eval);
}

PYBIND11_MODULE(PyBindTester, m) {
    declare<DerivedClass>(m, "DerivedClass");
}

我大致基于这个问题的答案PyBind11 Template Class of Many Types。但是我得到的错误是:

C2783 'pybind11::class_> &pybind11::class_>::def(const char *,Func &&,const Extra &...)': 无法推断 'Func' 的模板参数 ...\source。 cpp 10
C2672 'pybind11::class_>::def': 找不到匹配的重载函数 ...\source.cpp 12

这似乎与第二个template &lt;class FuncType&gt; 有关,我无法在任何地方定义它,因为通用函数func 稍后会传入。有没有办法规避这个问题?

【问题讨论】:

    标签: c++ templates pybind11


    【解决方案1】:

    eval 必须是接受双精度并返回双精度(或可转换为双精度的类型)的函数,因此您可以使用 &amp;DeclareClass::eval&lt;double(*)(double)&gt; 专门化模板;或者更好地包括&lt;functional&gt;&lt;pybind11/functional.h&gt;,您可以完全删除模板并使evalstd::function&lt;double(double)&gt; 作为其第一个参数。

    更具体地说,我将重写如下

    /* TestClass.hpp */
    #pragma once
    #include <functional>
    
    template <class Impl>
    class CurRecTemplate {
    protected:
        CurRecTemplate() {}
        ~CurRecTemplate() {}
    
        Impl& impl() { return static_cast<Impl&>(*this); }
        const Impl& impl() const { return static_cast<const Impl&>(*this); }
    };
    
    template <class Impl>
    class BaseClass : public CurRecTemplate<Impl> {
    public:
        BaseClass() { };
    
        double eval(std::function<double(double)> func, double x) const
        {
            return this->impl().evalImplementation(func, x);
        }
    };
    
    class DerivedClass : public BaseClass<DerivedClass> {
    public:
        double evalImplementation(std::function<double(double)> f, double x) const
        {
            return f(x);
        };
    }; 
    
    /* Source.cpp */
    #include <pybind11/pybind11.h>
    #include "TestClass.hpp"
    #include <pybind11/functional.h>
    
    namespace py = pybind11;
    
    template<typename Impl>
    void declare(py::module &m, const std::string& className) {
        using DeclareClass = BaseClass<Impl>;
    
        py::class_<DeclareClass, std::shared_ptr<DeclareClass>>(m, className.c_str())
            .def(py::init<>())
            .def("eval", &DeclareClass::eval);
    }
    
    PYBIND11_MODULE(Project1, m) {
        declare<DerivedClass>(m, "DerivedClass");
    }
    

    【讨论】:

    • 使用std::shared_ptr&lt;DeclareClass&gt;的原因是什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多