我有一个函数,它需要3个模板参数:两个类型和一个整数常量(用于Eigen存储要求)。它看起来像下面的模板:
template <typename VertexType, typename IndexType, Eigen::StorageOptions Options>
void my_big_function(/* 3 Eigen parameters depending on template args... */) {
/* Do stuff with matrices... */
}
字符串
而且由于这个函数需要绑定到python上的多个模板“三元组”,我想这可能是template parameter packs的一个很好的用法。
我想实现以下目标:
// binds to python :
// - my_big_function<float, int, ColMajor>(...)
bind_my_big_function<float, int, Eigen::ColMajor>(m); // (1)
// binds to python :
// - my_big_function<float, int, ColMajor>(...)
// - my_big_function<float, int, RowMajor>(...)
// - my_big_function<double, int, RowMajor>(...)
bind_my_big_function<float, int, Eigen::ColMajor, float, int, Eigen::RowMajor, double, int, Eigen::RowMajor>(m); // (2)
型bind_my_big_function
很简单:
template <typename MatVertexType, typename MatIndexType, Eigen::StorageOptions MatOptions, typename...RemainingArgs>
void bind_my_big_function(pybind11::module_& m) {
/* bind function taking MatVertexType, MatIndexType & MatOptions and go onto binding other variants of my_big_function */
}
型
虽然我肯定可以生成一些处理case(1)的代码,但我不知道如何编写处理case(2)的代码。我得到的最接近的代码是这样的:
template <typename MatVertexType, typename MatIndexType, Eigen::StorageOptions MatOptions>
void bind_my_big_function(pybind11::module_& m) {
m.def("my_big_function_in_python", &my_big_function<MatVertexType, MatIndexType, MatOptions>, /* python arguments...*/);
}
template <
typename MatVertexType, typename MatIndexType, Eigen::StorageOptions MatOptions,
typename...RemainingArgs, typename = typename std::enable_if_t<sizeof...(RemainingArgs) != 0>
>
void bind_my_big_function(pybind11::module_& m) {
m.def("my_big_function_in_python", &my_big_function<MatVertexType, MatIndexType, MatOptions>, /* python arguments...*/);
bind_my_big_function<RemainingArgs...>(m);
}
型
参数包应该以这种方式使用吗?我能找到的使用它们的例子只有:
- 使用模板化的函数参数,
- 一次使用一个包扩展“用法”(被调用的函数只需要一个类型和一个可变模板包)
3条答案
按热度按时间ogsagwnx1#
你还不能在一个包中捕获混合类型(
MatVertexType
,MatIndexType
)和非类型(MatOptions
)的模板参数,因为从C23开始,一个包必须是单一类型的:类型(typename
/class
),template
,或值(具体或auto
)。有几个可能的解决方案:
1.将非类型模板参数提升到类型空间,例如使用
std::integral_constant<Eigen::StorageOption>
,以便它可以与类型参数一起传递到类型包中;1.合并将每个三元组的相关参数组合成一个类型,例如
template<class MatVertexType, class MatIndexType, Eigen::StorageOption MatOptions> struct MatParameters;
(这是AOS选项);1.(如您的解决方案https://stackoverflow.com/a/77488183/567292)传递三个同构包,例如使用
std::tuple
作为类型包,std::integer_sequence
(在类型空间中)或std::array
(在值空间中)作为值包(这是选项2的SOA变体);1.等待“Universal Template Parameters“,它已经被提议用于C26。
puruo6ea2#
不知道我是否理解了这个问题,但是如果你想在给定
Ts...
的情况下示例化一些foo<Ts...,Ts...,Ts...>
,你可以 Package 函数模板,只需要示例化它:字符串
brvekthn3#
为了让其他人也这么做,我最后做了以下事情。
我将模板“triplets”的每个参数打包到类似元组的空结构中,并使用递归调用元组执行打包扩展。下面是结果代码的粗略框架:
字符串
函数调用中的所有元组参数仅用于重载解析和包扩展。
因为在递归绑定函数中,每个参数包都被一个“具体”类型包围,所以我可以在编译时对所有三个参数包进行编译,并生成对
pybind11::module_::def()
的所有调用。下面是一个如何调用该函数并解析所有调用的示例:型