【问题标题】:A smart way to export c++ polymorphic functions with boost.python用 boost.python 导出 c++ 多态函数的聪明方法
【发布时间】:2011-07-04 09:45:25
【问题描述】:

我有一个高度多态的 c++ 函数,可以用近 20 种不同的类型调用。

为了将它暴露给 python,我正在做这样的事情:

#include originalFunctionNamespace.hpp

template<class T>
    T foo(T x)
    {
        return orignalFunctionNamespace::foo(x);
    }

但是要从 python 调用它们,我必须使用它们支持的每种类型来专门化函数:

BOOST_PYTHON_MODULE(module_foo)
{
    def("foo", foo<orignalFunctionNamespace::type1>);
    def("foo", foo<orignalFunctionNamespace::type2>);
    def("foo", foo<orignalFunctionNamespace::type3>);
    def("foo", foo<orignalFunctionNamespace::type4>);
    def("foo", foo<orignalFunctionNamespace::type5>);
    def("foo", foo<orignalFunctionNamespace::type6>);
    def("foo", foo<orignalFunctionNamespace::type7>);
    ...
    ...
    ...
    def("foo", foo<orignalFunctionNamespace::typeN>);
}

这可行,但我不能停止认为必须有更聪明的方法来做到这一点。由于我必须为许多功能执行此操作,因此事情变得越来越大并且超级重复。 有什么建议吗?

【问题讨论】:

  • 这好像不是多态,只是函数重载。
  • 不是更好的方法,但您可以尝试使用预处理器缩短每一行并“使用命名空间 originalFunctionNamespace;”进一步缩短它们。那个deos不能解决重复,但至少可以为你节省很多文本。
  • @interjay 该函数可以接收多种类型作为输入,并相应地输出多种不同类型。 “可以评估或应用于不同类型值的函数称为多态函数。”对吗?
  • @Nobody: 不会“使用命名空间 originalFunctionNamespace;”阻止我对 python 中的函数使用相同的名称?反正我知道你的意思,tnx :)
  • @quiuquio:我不会调用这种多态性,因为调用的实际函数是在编译时确定的,而不是动态确定的。另外,在 C++ 的上下文中,术语多态性是指具有虚函数的对象。

标签: c++ python templates boost polymorphism


【解决方案1】:

对我来说,这似乎是 typelist 魔法的一种可能用途。

如果您正在使用(或可以使用)新的 C++0x 标准,您可以编写如下内容:

template <typename ArgType>
void def_foo_overloads()
{
    def("foo", foo<ArgType>);
    // last type in list
}
template <typename ArgType, typename... MoreArgTypes>
void def_foo_overloads()
{
    def("foo", foo<ArgType>);
    def_foo_overloads(MoreArgTypes...);
}

// use it like:
def_foo_overloads<orignalFunctionNamespace::type1,
                  orignalFunctionNamespace::type2,
                  ...
                  orignalFunctionNamespace::typeN> ();

如果您无法访问新标准,则可以使用旧的递归类型列表执行等效操作。

【讨论】:

  • 或:template&lt;typename... Types&gt; void def_overloads() { std::initializer_list&lt;int&gt; { (def("foo", foo&lt;Types&gt;), void(), 0)... }; }
  • 它也不特定于std::initializer_list&lt;T&gt;。使用新列表初始化语法的每个构造都保证了其参数的评估顺序,即使它等同于例如构造函数调用(其中唯一的保证是进入构造函数主体之前的序列点,像往常一样)。所以例如std::pair&lt;int, int&gt;(++i, ++i) 不好,而 std::pair&lt;int, int&gt; { ++i, ++i } 很好。此处使用std::initializer,因为它可以接受任意数量的参数。我个人使用带有可变参数构造函数的空类型。
  • @Useless:对不起,但是..不是一回事吗?从“//use is like:”我了解到,我必须以与以前相同的方式编写每个函数特化,并且必须为每个函数创建一个 def_XXX_overloads()。这就是说,类型列表可能是我问题的关键。谢谢!
  • 这种方法的要点是您可以编写一个def_overloads 函数模板,并将所有有效参数类型的列表传递给它。除了列出参数类型之外,您不会为每个重载编写任何额外的内容。现在,如果您设置了多个要处理的函数重载(假设您有一组称为 bar 的类似函数也采用不同的参数类型),您可能需要一些更棘手的东西来通过重载函数参数化 def_overloads姓名。你是这个意思吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-07-12
  • 1970-01-01
  • 2016-07-30
  • 1970-01-01
  • 2011-07-02
  • 2014-12-03
  • 2014-07-05
相关资源
最近更新 更多