Целочисленные параметры шаблона и вызовы подфункций

В этом коротком фрагменте я хочу создать 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());

Я попытался использовать простое решение с этого сайта, но оно говорит мне "не может конвертировать из 'ints<5,4,3,2,1,0>' в 'int'".

Еще раз спасибо Jarod42,

array<int, sizeof...(Is)> shuffle_tens = { (sizeof...(Is) - Is - 1)... };

работает для меня.

1 ответ

Решение

Вы могли бы использовать 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.

Другие вопросы по тегам