将模板类型传递给函数并用于局部变量赋值 C++
Issue passing template type to function and using for local variable assignment c++
我有以下代码:
template<typename T> void computeFractalDimensionData(RandomWalkMethods::LatticeType latticeType, gsl_rng* randNumGen) {
int nD = 0;
// if T is of type std::pair<int,int> then set no. of dimensions to 2
if (typeid(T) == typeid(std::pair<int, int>)) {
nD = 2;
}
// else if T is of type RWM::Triple<int,int,int> then set no. of dimensions to 3
else if (typeid(T) == typeid(RandomWalkMethods::Triple<int, int, int>)) {
nD = 3;
}
else {
return;
}
// Create vector of T structs to store DLA structure results
std::vector<T> aggResults;
// Initialise particle spawning type and attractor type for DLA system
RandomWalkMethods::ParticleSpawnType spawn = RandomWalkMethods::CONSTANT_RANDOM_BOUNDINGBOX_EDGE;
RandomWalkMethods::AttractorDLAType attractor = RandomWalkMethods::POINT;
// Under-estimate for fractal dimension of the DLA
const double fractalDimUnderestimateRecip = 1 / 1.65;
for (int i = 100; i <= 1000; i += 100) {
// initialise spawnDiameter using: exp(log(n)/fDUR) = n^{1/fDUR}
int spawnDiam = 2*static_cast<int>(std::pow(i, fractalDimUnderestimateRecip));
// if system is 2-dimensional, compute DLA for 2D on given lattice
if (nD == 2) {
aggResults = RandomWalkMethods::diffusionLimitedAggregateRandomWalk2D(i, spawn, spawnDiam, latticeType, randNumGen, attractor);
}
// else if system is 3 dimensional, compute DLA for 3D on given lattice
else if (nD == 3) {
aggResults = RandomWalkMethods::diffusionLimitedAggregateRandomWalk3D(i, spawn, spawnDiam, latticeType, randNumGen, attractor);
}
// compute the minimum bounding radius which encloses all particles in the DLA structure
double boundingRadius = std::sqrt(maxMagnitudeVectorOfMultiples< double, T >(aggResults));
}
}
我可以用
这样的语句调用
computeFractalDimensionData< std::pair<int,int> >(lattice, randNumGen);
或
computeFractalDimensionData< RandomWalkMethods::Triple<int,int,int> >(lattice, randNumGen);
其中 Triple
只是我用 3 个元素定义的结构(与 std::pair
基本相同,但扩展了 3 个字段)。另外,函数 diffusionLimitedAggregateRandomWalk2D
和 diffusionLimitedAggregateRandomWalk3D
return 类型分别为 std::vector<std::pair<int,int>>
和 std::vector<Triple<int,int,int>>
。
问题是,当我用上面的任一语句调用时,我得到以下错误(发生在赋值语句 aggResults = ...
):
binary '=': no operator found which takes a right-hand operand of type 'std::vector<std::pair<int,int>,std::allocator<_Ty>>' (or there is no acceptable conversion)
和 Triple<int,int,int>
的情况类似。据我了解,这意味着我需要为这 2 个结构重载赋值运算符 - 但是我不认为这是这里的问题,因为之前在我的程序中正确使用了以下语句:
std::vector< std::pair<int,int> > aggResults = RandomWalkMethods::diffusionLimitedAggregateRandomWalk2D(nParticles, boundingBox, spawnDiam, latticeType, randNumGen, attractor, &diffLimAggFile);
所以我知道我可以将 DLA 方法的结果分配给正确类型的变量,但是如果我通过使用将类型传递给模板函数来尝试它,编译器会抱怨,如上所示。
这里发生了什么,我将如何解决这个问题?
这是因为
aggResults = diffusionLimitedAggregateRandomWalk2D(i, spawn, spawnDiam, latticeType, randNumGen, attractor);
with aggResults
being a std::vector<T>
即使 T
is Triple<int, int, int>
but diffusionLimitedAggregateRandomWalk2D
returns a std::vector<std::pair<int, int>>
也会被编译.
建议的解决方案:声明一个模板化函数并将其专门用于某些 T
.
template<typename T>
void computeFractalDimensionData(RandomWalkMethods::LatticeType latticeType, gsl_rng* randNumGen);
template<>
void computeFractalDimensionData<std::pair<int, int>>(RandomWalkMethods::LatticeType latticeType, gsl_rng* randNumGen)
{
// ...
}
template<>
void computeFractalDimensionData<Triple<int, int, int>>(RandomWalkMethods::LatticeType latticeType, gsl_rng* randNumGen)
{
// ...
}
它使代码更具可读性并且无法编译以下行并出现帮助编译错误:
computeFractalDimensionData<void>(lattice, randNumGen);
YSC的方案不错。我希望您注意函数中的以下代码是对模板的错误使用:
// if system is 2-dimensional, compute DLA for 2D on given lattice
if (nD == 2) {
aggResults = RandomWalkMethods::diffusionLimitedAggregateRandomWalk2D(i, spawn, spawnDiam, latticeType, randNumGen, attractor);
}
// else if system is 3 dimensional, compute DLA for 3D on given lattice
else if (nD == 3) {
aggResults = RandomWalkMethods::diffusionLimitedAggregateRandomWalk3D(i, spawn, spawnDiam, latticeType, randNumGen, attractor);
}
模板用于静态多态,而您在模板函数中使用动态代码(这些if (nd == ...)
)。正确使用静态多态性可以引入模板参数 dimension
.
我有以下代码:
template<typename T> void computeFractalDimensionData(RandomWalkMethods::LatticeType latticeType, gsl_rng* randNumGen) {
int nD = 0;
// if T is of type std::pair<int,int> then set no. of dimensions to 2
if (typeid(T) == typeid(std::pair<int, int>)) {
nD = 2;
}
// else if T is of type RWM::Triple<int,int,int> then set no. of dimensions to 3
else if (typeid(T) == typeid(RandomWalkMethods::Triple<int, int, int>)) {
nD = 3;
}
else {
return;
}
// Create vector of T structs to store DLA structure results
std::vector<T> aggResults;
// Initialise particle spawning type and attractor type for DLA system
RandomWalkMethods::ParticleSpawnType spawn = RandomWalkMethods::CONSTANT_RANDOM_BOUNDINGBOX_EDGE;
RandomWalkMethods::AttractorDLAType attractor = RandomWalkMethods::POINT;
// Under-estimate for fractal dimension of the DLA
const double fractalDimUnderestimateRecip = 1 / 1.65;
for (int i = 100; i <= 1000; i += 100) {
// initialise spawnDiameter using: exp(log(n)/fDUR) = n^{1/fDUR}
int spawnDiam = 2*static_cast<int>(std::pow(i, fractalDimUnderestimateRecip));
// if system is 2-dimensional, compute DLA for 2D on given lattice
if (nD == 2) {
aggResults = RandomWalkMethods::diffusionLimitedAggregateRandomWalk2D(i, spawn, spawnDiam, latticeType, randNumGen, attractor);
}
// else if system is 3 dimensional, compute DLA for 3D on given lattice
else if (nD == 3) {
aggResults = RandomWalkMethods::diffusionLimitedAggregateRandomWalk3D(i, spawn, spawnDiam, latticeType, randNumGen, attractor);
}
// compute the minimum bounding radius which encloses all particles in the DLA structure
double boundingRadius = std::sqrt(maxMagnitudeVectorOfMultiples< double, T >(aggResults));
}
}
我可以用
这样的语句调用computeFractalDimensionData< std::pair<int,int> >(lattice, randNumGen);
或
computeFractalDimensionData< RandomWalkMethods::Triple<int,int,int> >(lattice, randNumGen);
其中 Triple
只是我用 3 个元素定义的结构(与 std::pair
基本相同,但扩展了 3 个字段)。另外,函数 diffusionLimitedAggregateRandomWalk2D
和 diffusionLimitedAggregateRandomWalk3D
return 类型分别为 std::vector<std::pair<int,int>>
和 std::vector<Triple<int,int,int>>
。
问题是,当我用上面的任一语句调用时,我得到以下错误(发生在赋值语句 aggResults = ...
):
binary '=': no operator found which takes a right-hand operand of type 'std::vector<std::pair<int,int>,std::allocator<_Ty>>' (or there is no acceptable conversion)
和 Triple<int,int,int>
的情况类似。据我了解,这意味着我需要为这 2 个结构重载赋值运算符 - 但是我不认为这是这里的问题,因为之前在我的程序中正确使用了以下语句:
std::vector< std::pair<int,int> > aggResults = RandomWalkMethods::diffusionLimitedAggregateRandomWalk2D(nParticles, boundingBox, spawnDiam, latticeType, randNumGen, attractor, &diffLimAggFile);
所以我知道我可以将 DLA 方法的结果分配给正确类型的变量,但是如果我通过使用将类型传递给模板函数来尝试它,编译器会抱怨,如上所示。
这里发生了什么,我将如何解决这个问题?
这是因为
aggResults = diffusionLimitedAggregateRandomWalk2D(i, spawn, spawnDiam, latticeType, randNumGen, attractor);
with aggResults
being a std::vector<T>
即使 T
is Triple<int, int, int>
but diffusionLimitedAggregateRandomWalk2D
returns a std::vector<std::pair<int, int>>
也会被编译.
建议的解决方案:声明一个模板化函数并将其专门用于某些 T
.
template<typename T>
void computeFractalDimensionData(RandomWalkMethods::LatticeType latticeType, gsl_rng* randNumGen);
template<>
void computeFractalDimensionData<std::pair<int, int>>(RandomWalkMethods::LatticeType latticeType, gsl_rng* randNumGen)
{
// ...
}
template<>
void computeFractalDimensionData<Triple<int, int, int>>(RandomWalkMethods::LatticeType latticeType, gsl_rng* randNumGen)
{
// ...
}
它使代码更具可读性并且无法编译以下行并出现帮助编译错误:
computeFractalDimensionData<void>(lattice, randNumGen);
YSC的方案不错。我希望您注意函数中的以下代码是对模板的错误使用:
// if system is 2-dimensional, compute DLA for 2D on given lattice
if (nD == 2) {
aggResults = RandomWalkMethods::diffusionLimitedAggregateRandomWalk2D(i, spawn, spawnDiam, latticeType, randNumGen, attractor);
}
// else if system is 3 dimensional, compute DLA for 3D on given lattice
else if (nD == 3) {
aggResults = RandomWalkMethods::diffusionLimitedAggregateRandomWalk3D(i, spawn, spawnDiam, latticeType, randNumGen, attractor);
}
模板用于静态多态,而您在模板函数中使用动态代码(这些if (nd == ...)
)。正确使用静态多态性可以引入模板参数 dimension
.