在这个简短的片段中,我想创建一个Eigen :: Tensor(在不支持的模块中),具有aribtrary维度。
template
<typename T>
Tensor<T, 2> convertNPToEigen2D(np::ndarray const & arr)
{
//Some checking...
T* raw_arr_data = reinterpret_cast<T*>(arr.get_data());
TensorMap<Tensor<T, 2>> arr_eigen(raw_arr_data,
arr.shape(0), arr.shape(1));
//...
return arr_eigen;
}
您当然可以看到,如果没有可变参数模板,我必须为每个可能的维数复制此函数。这似乎是一个非常基本的例子,其中可变参数模板可以避免大量的代码重复:
template
<typename T, uint64_t dims>
Tensor<T, dims> convertNPToEigenND(np::ndarray const & arr)
{
//Some checking...
T* raw_arr_data = reinterpret_cast<T*>(arr.get_data());
TensorMap<Tensor<T, dims>> arr_eigen(raw_arr_data,
/*arr.shape(0), ..., arr.shape(dims-1)*/);
//...
return arr_eigen;
}
我有几个问题将其转换为可变参数模板代码,因为我没有参数包。我想也可以让调用者完成工作,即
convertNPToEigenND<float, arr.shape(0), arr.shape(1), arr.shape(2)>(arr)
但如果有可能,我更愿意采用上述解决方案。 我认为很容易看出这个问题,但我发现的大多数问题都是处理现有的参数包而不是创建一个。
提前致谢!
谢谢,解决方案非常有效。我需要的另一个简单的扩展是:
array<int, sizeof...(Is)> shuffle_tens = { Is... };
reverse(shuffle_tens.begin(), shuffle_tens.end());
我尝试使用来自this site的简单解决方案,但它告诉我“无法转换为'ints&lt; 5,4,3,2,1,0&gt;'到'int'“。
再次感谢Jarod42,
array<int, sizeof...(Is)> shuffle_tens = { (sizeof...(Is) - Is - 1)... };
适合我。
答案 0 :(得分:2)
您可以使用std::index_sequence
:
template <typename T, size_t ... Is>
Tensor<T, sizeof...(Is)> convertNPToEigenNDHelper(np::ndarray const & arr,
std::index_sequence<Is...>)
{
//Some checking...
T* raw_arr_data = reinterpret_cast<T*>(arr.get_data());
TensorMap<Tensor<T, sizeof...(Is)>> arr_eigen(raw_arr_data, arr.shape(Is)...);
//...
return arr_eigen;
}
template
<typename T, uint64_t dims>
Tensor<T, dims> convertNPToEigenND(np::ndarray const & arr)
{
return convertNPToEigenNDHelper<T>(arr, std::make_index_sequence<dims>());
}
std::index_sequence
/ std::make_index_sequence
是C ++ 14,但可以在C ++ 11中实现。