Я только начал использовать Eigen и прочитал из их документации, что лучшая производительность достигается из-за их ленивой оценки матричных выражений. Следовательно, подобные выражения очень эффективны после вычисления:
Eigen::Matrix<float, 3, 1> a;
a << 0, 1, 2;
Eigen::Matrix<float, 3, 1> b;
b << 3, 4, 5;
Eigen::Matrix<float, 3, 1> c;
c << (a + b).sum(),
(a - b).sum(),
a.sum();
std::cout << c << std::endl;
Я столкнулся с проблемой при построении матриц, число столбцов которых зависит от параметра шаблона. Например:
template <std::size_t w>
auto buildGradient() {
Eigen::Matrix<float, 3, w> matrix;
matrix << /* ? */;
return matrix;
}
Первым делом я хотел использовать рекурсивный шаблон c ++.
template <std::size_t w, typename Functor>
auto buildGradientExpr(Functor functor) {
if constexpr (w == 0) {
return;
} else if constexpr (w == 1) {
return functor();
} else {
return functor(), buildGradientExpr<w - 1, Functor>(functor);
}
}
Но использование этого приводит к ошибкам времени выполнения, генерируемым Eigen, поскольку выражение только имеет один инициализатор.
template <std::size_t w>
auto buildGradient() {
Eigen::Matrix<float, 3, w> gradient;
/* Emits an error about too few coefficients being passed to the initializer. */
gradient << buildGradientExpr<w>([]() { /* Return 3x1 matrix */ });
return gradient;
}
Вот полный исполняемый пример.
#include <Eigen/Dense>
#include <iostream>
#include <cstddef>
namespace {
template <std::size_t w, typename Functor>
auto buildGradientExpr(Functor functor) {
if constexpr (w == 0) {
return;
} else if constexpr (w == 1) {
return functor(w);
} else {
return functor(w), buildGradientExpr<w - 1, Functor>(functor);
}
}
template <std::size_t w, typename Functor>
auto buildGradient(Functor functor) {
Eigen::Matrix<float, 3, w> gradient;
gradient << buildGradientExpr<w>(functor);
return gradient;
}
} // namespace
int main() {
constexpr std::size_t gradient_width = 10;
auto gradient_functor = [](std::size_t w) {
return Eigen::Matrix<float, 3, 1>::Constant(float(w) / gradient_width);
};
auto gradient = buildGradient<gradient_width>(gradient_functor);
std::cout << gradient << std::endl;
return 0;
}
Существует ли способ построения матриц с размерами, которые зависят от параметров шаблона, без обращения к a для l oop? Ничего против петель, это то, что я использую в то же время. Я просто хотел бы знать, есть ли способ инициализировать матричное выражение, используя циклы шаблона.
Редактировать: * Я обновил пример, потому что функтор градиента должен был возвращать вектор а не скаляр. Однако возникает проблема с примером.