I work on an existing C++11 project where I have a problem with creating an array of pointers. Unfortunately, the error does not persist in the minimal example.
The member function of a templated class I want to call takes a two by two
array of FullCloverBlock
pointers, like this:
void two_flav_achimbdpsi(FourSpinorBlock *res[2],
const FourSpinorBlock *chi[2],
const FourSpinorBlock *psi[2],
const SU3MatrixBlock *u,
FullCloverBlock *clov[2][2],
const double beta,
const double epsilon,
const int isign,
const int cb);
In the test for this function, a bunch of fields are declared for use in all tests:
FullClover *A_cb0_plus = (FullClover *)geom.allocCBFullClov();
FullClover *A_cb0_minus = (FullClover *)geom.allocCBFullClov();
FullClover *A_cb1_plus = (FullClover *)geom.allocCBFullClov();
FullClover *A_cb1_minus = (FullClover *)geom.allocCBFullClov();
FullClover *clov_packed[2][2];
clov_packed[0][0] = A_cb0_plus;
clov_packed[0][1] = A_cb0_minus;
clov_packed[1][0] = A_cb1_plus;
clov_packed[1][1] = A_cb1_minus;
The type FullClover
and FullCloverBlock
are the same, there are just
different typedef
s in the different files.
Then later in that function I build a container to hold the quantity of interest. I want to use the same thing twice, this is needed for the application.
FullClover **two_flav_clov[2] = {clov_packed[target_cb],
clov_packed[target_cb]};
Then I try to call the function using that new variable:
tmdslash.two_flav_achimbdpsi(two_flav_res,
two_flav_chi,
two_flav_psi,
u_packed[target_cb],
two_flav_clov,
beta,
epsilon,
isign,
target_cb);
I would expect the type of two_flav_clov
to be FullClover ***
or
equivalent. This should match the type needed in the function
two_flav_achimbdpsi
that I want to call. However, I get the following error:
tests/testNDTMvsTMCloverFull.cc: In instantiation of 'void testNDTMvsTMCloverFull::runTest() [with FT = float; int V = 8; int S = 4; bool compress = true; U = QDP::OLattice<QDP::PScalar<QDP::PColorMatrix<QDP::RComplex<float>, 3> > >; Phi = QDP::OLattice<QDP::PSpinVector<QDP::PColorVector<QDP::RComplex<float>, 3>, 4> >]':
tests/testNDTMvsTMCloverFull.cc:838:58: required from here
tests/testNDTMvsTMCloverFull.cc:421:17: error: no matching function for call to 'QPhiX::TMClovDslash<float, 8, 4, true>::two_flav_achimbdpsi(float (* [2])[3][4][2][4], float (* [2])[3][4][2][4], float (* [2])[3][4][2][4], float (*&)[8][2][3][2][8], FullClover** [2], double&, const double&, int&, int&)'
tmdslash.two_flav_achimbdpsi(two_flav_res,
^~~~~~~~
In file included from include/qphix/tm_clov_dslash_def.h:376:0,
from include/qphix/qdp_packer_parscalar.h:21,
from include/qphix/qdp_packer.h:15,
from tests/testNDTMvsTMCloverFull.cc:24:
include/qphix/tm_clov_dslash_body.h:1817:10: note: candidate: void QPhiX::TMClovDslash<FT, veclen, soalen, compress12>::two_flav_achimbdpsi(QPhiX::TMClovDslash<FT, veclen, soalen, compress12>::FourSpinorBlock**, const FourSpinorBlock**, const FourSpinorBlock**, const SU3MatrixBlock*, QPhiX::TMClovDslash<FT, veclen, soalen, compress12>::FullCloverBlock* (*)[2], double, double, int, int) [with FT = float; int veclen = 8; int soalen = 4; bool compress12 = true; QPhiX::TMClovDslash<FT, veclen, soalen, compress12>::FourSpinorBlock = float [3][4][2][4]; QPhiX::TMClovDslash<FT, veclen, soalen, compress12>::SU3MatrixBlock = float [8][2][3][2][8]; QPhiX::TMClovDslash<FT, veclen, soalen, compress12>::FullCloverBlock = QPhiX::Geometry<float, 8, 4, true>::FullCloverBlock]
void TMClovDslash<FT, veclen, soalen, compress12>::two_flav_achimbdpsi(
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/qphix/tm_clov_dslash_body.h:1817:10: note: no known conversion for argument 5 from 'FullClover** [2] {aka QPhiX::Geometry<float, 8, 4, true>::FullCloverBlock** [2]}' to 'QPhiX::TMClovDslash<float, 8, 4, true>::FullCloverBlock* (*)[2] {aka QPhiX::Geometry<float, 8, 4, true>::FullCloverBlock* (*)[2]}'
The core seems to be that it cannot convert FullClover** [2]
to
FullCloverBlock* (*)[2]
. This syntax with the parentheses is new to me. What
does it mean?
The following is a minimal example that I think should do the same thing. However, it does not fail to compile.
struct FullClover {
int x;
};
void achimdpsi(FullClover *clov[2][2]) {}
int main(int argc, char **argv) {
FullClover *A;
FullClover *clov_packed[2][2];
clov_packed[0][0] = A;
clov_packed[0][1] = A;
clov_packed[1][0] = A;
clov_packed[1][1] = A;
int cb;
FullClover **two_flav_clover[2] = {clov_packed[cb], clov_packed[cb]};
achimdpsi(clov_packed);
}
Therefore I am not sure what happens here, the minimal example should show the same errors, if the problem was indeed the type.
What is going on here? How can I fix this?