I have a function that accepts N position vectors and updates them:
using Vector3r = Eigen::Matrix<Real, 3, 1, Eigen::DontAlign>;
template<unsigned int N>
using Vectorr = Eigen::Matrix<Real, N, 1, Eigen::DontAlign>;
template <unsigned int N>
bool solveFbd(const std::reference_wrapper<Vector3r> (&positions)[N]);
The force
I have another function that accepts N position vectors and gives the force
template <unsigned int N>
void forceInternal(const std::reference_wrapper<Vector3r> (&positions)[N], Vectorr<N*3>& forces);
Until now I was simply passing the positions parameter inside solveFbd
as an argument to a forceInternal
call.
forceInternal(positions);
I copied the type parameter of parameter position
for forceInternal
from solveFbd
blindly, however I don't modify positions
in this so it should have ideally been const std::reference_wrapper<const Vector3r> (&positions)[N]
. Unfortunately adding this extra const
gives me errors with this call. If there is some way to do convert the positions to std::reference_wrapper<const Vector3r> (&positions)[N]
it would greatly help but it is not the main problem I am facing here.
Now, I also need to do something like this:
Vector3r positionsCopy[N];
Vectorr<3*N> forces;
for (unsigned int p = 0; p < N; p++)
{
// I need to make a copy here, I can't change that original `positions`
positionsCopy[p] = positions[p] + delta[p];
}
forceInternal(positionsCopy, forces);
Unfortunately I get this error when the function solveFbd
is instantiated with template parameter 3u
:
C:\Users\sin3point14\my-projs\gpbd\PositionBasedDynamics\FBD.cpp(581): error C2664: '_Ret std::_Func_class<_Ret,const std::reference_wrapper<Vector3r> (&)[3],Eigen::Matrix<Real,9,1,2,9,1> &>::operator ()(const std::reference_wrapper<Vector3r> (&)[3],Eigen::Matrix<Real,9,1,2,9,1> &) const': cannot convert argument 1 from 'Vector3r [3]' to 'const std::reference_wrapper<Vector3r> (&)[3]'
with
[
_Ret=void
]
C:\Users\sin3point14\my-projs\gpbd\PositionBasedDynamics\FBD.cpp(581): note: Reason: cannot convert from 'Vector3r [3]' to 'const std::reference_wrapper<Vector3r> [3]'
C:\Users\sin3point14\my-projs\gpbd\PositionBasedDynamics\FBD.cpp(581): note: There is no context in which this conversion is possible
From the error I understood that the conversion isn't possible, but I don't want to make a separate overload for forceInternal
to accept Vector3r [3]
. There are many such forceInternal
functions for different force models in my codebase. Is it possible to somehow modify my existing solveFbd
or forceInternal
to handle my problem.
minimal reproducible example:
#include <Eigen/Dense>
using Real = double;
using Vector3r = Eigen::Matrix<Real, 3, 1, Eigen::DontAlign>;
template<unsigned int N>
using Vectorr = Eigen::Matrix<Real, N, 1, Eigen::DontAlign>;
template <unsigned int N>
void forceInternal(const std::reference_wrapper<Vector3r>(&positions)[N], Vectorr<N * 3>& forces)
{
// do some stuff
}
template <unsigned int N>
bool solveFbd(const std::reference_wrapper<Vector3r>(&positions)[N])
{
Vectorr<N * 3> forces;
forceInternal(positions, forces); // no issues here
Vector3r positionsCopy[N];
Vector3r delta[N];
for (unsigned int p = 0; p < N; p++)
{
// I need to make a copy here, I can't change that original `positions`
positionsCopy[p] = positions[p].get() + delta[p];
}
forceInternal(positionsCopy, forces); // error
}
int main()
{
Vector3r x1, x2, x3;
solveFbd({ x1, x2, x3 });
}
Error:
Build started...
1>------ Build started: Project: ConsoleApplication4, Configuration: Debug x64 ------
1>ConsoleApplication4.cpp
1>C:\Users\sin3point14\my-projs\ConsoleApplication4\ConsoleApplication4\ConsoleApplication4.cpp(27,5): error C2672: 'forceInternal': no matching overloaded function found
1>C:\Users\sin3point14\my-projs\ConsoleApplication4\ConsoleApplication4\ConsoleApplication4.cpp(10,6): message : could be 'void forceInternal(const std::reference_wrapper<Vector3r> (&)[N],Eigen::Matrix<Real,N*3,1,2,_Rows,1> &)'
1>C:\Users\sin3point14\my-projs\ConsoleApplication4\ConsoleApplication4\ConsoleApplication4.cpp(27,5): message : 'void forceInternal(const std::reference_wrapper<Vector3r> (&)[N],Eigen::Matrix<Real,N*3,1,2,_Rows,1> &)': could not deduce template argument for 'const std::reference_wrapper<Vector3r> (&)[N]' from 'Vector3r [3]'
1>C:\Users\sin3point14\my-projs\ConsoleApplication4\ConsoleApplication4\ConsoleApplication4.cpp(33,2): message : see reference to function template instantiation 'bool solveFbd<3>(const std::reference_wrapper<Vector3r> (&)[3])' being compiled
1>Done building project "ConsoleApplication4.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
========== Build started at 5:55 PM and took 01.610 seconds ==========
You can make the function template accept arrays of any type:
template <typename T, unsigned int N>
void forceInternal(const T(&positions)[N], Vectorr<N * 3>& forces)
{
// do some stuff
}
If necessary you can add constraints that T
must be either td::reference_wrapper<Vector3r>
or Vector3r
.
You miss to return a value from solveFbd
. After fixing that your code looks ok: https://godbolt.org/z/Ts4TMbfK7