I am trying to calculate the lpNorm of a vector with the Eigen library.
As it can be seen in the example below, with explicit values, such as v.lpNorm<1>(), it works. But it doesn't work inside the loop, with lpNorm<p>()
How can I fix this?
#include <iostream>
#include <Eigen/Dense>
using Eigen::VectorXd;
int main()
{
int sizev = 3;
int p;
Eigen::VectorXd v(sizev);
v(0) = 3.;
v(1) = 2.;
v(2) = 1.;
// test 1, passes
std::cout << "||v||_" << 1 << " = " << v.lpNorm<1>() << std::endl;
std::cout << "||v||_" << 2 << " = " << v.lpNorm<2>() << std::endl;
std::cout << "||v||_" << 3 << " = " << v.lpNorm<3>() << std::endl;
std::cout << "||v||_" << 4 << " = " << v.lpNorm<4>() << std::endl;
std::cout << "||v||_inf = " << v.lpNorm<Eigen::Infinity>() << std::endl;
// test 2, fails
for (int p=1; p<5; p )
{
std::cout << "||v||_" << p << " = " << v.lpNorm<p>() << std::endl;
}
return 0;
}
On compilation, I am getting the error
error: no matching member function for call to 'lpNorm'
std::cout << "||v||_" << p << " = " << v.lpNorm<p>() << std::endl;
~~^~~~~~~~~
note: candidate template ignored: invalid explicitly-specified argument for template parameter 'p'
template<int p> EIGEN_DEVICE_FUNC RealScalar lpNorm() const;
^
1 error generated.
CodePudding user response:
You cannot use variable integer as a template argument, it needs to be a compile time constant, such as
constexpr int p = 3;
v.lpNorm<p>();
However, you can still have a kind of compile-time loop using e.g. std::integer_sequence. I modified a bit the example from documentation to call a function:
template<typename T, T... ints>
void exec_constexpr_loop(std::integer_sequence<T, ints...> int_seq, Eigen::Ref<Eigen::VectorXd> v)
{
((v.lpNorm<ints>()), ...);
}
exec_constexpr_loop(std::integer_sequence<int, 1, 2, 3>{}, v);
Live demo with dummy function, works since C 17.