问题将模板类型传递给函数并用于局部变量赋值 c++

Posted

技术标签:

【中文标题】问题将模板类型传递给函数并用于局部变量赋值 c++【英文标题】:Issue passing template type to function and using for local variable assignment c++ 【发布时间】:2016-04-02 09:51:23 【问题描述】:

我有以下代码:

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 个字段)。此外,函数diffusionLimitedAggregateRandomWalk2DdiffusionLimitedAggregateRandomWalk3D 分别返回std::vector&lt;std::pair&lt;int,int&gt;&gt;std::vector&lt;Triple&lt;int,int,int&gt;&gt; 的类型。

问题是,当我使用上述任一语句调用时,我收到以下错误(发生在赋值语句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&lt;int,int,int&gt; 的情况也是如此。据我了解,这意味着我需要为这 2 个结构使用重载的赋值运算符 - 但是我认为这不是问题所在,因为之前在我的程序中正确使用了以下语句:

std::vector< std::pair<int,int> > aggResults = RandomWalkMethods::diffusionLimitedAggregateRandomWalk2D(nParticles, boundingBox, spawnDiam, latticeType, randNumGen, attractor, &diffLimAggFile);

所以我知道我可以将 DLA 方法的结果分配给正确类型的变量,但是如果我通过使用将类型传递给模板函数来尝试它,编译器会报错,如上所示。

这里发生了什么,我将如何解决这个问题?

【问题讨论】:

@AngelusMortis 什么。我见过更长的。问题。尤其是更不可读的。 你可以用std::tuple代替自制的Triple和std::pair:en.cppreference.com/w/cpp/utility/tuple。看看助手类tuple_size @AndyT 不幸的是,这段代码必须在只有 C++98 兼容性的非常旧的服务器上运行,因此我无法使用 std::tuple :( 【参考方案1】:

这是因为

aggResults = diffusionLimitedAggregateRandomWalk2D(i, spawn, spawnDiam, latticeType, randNumGen, attractor);

如果aggResultsstd::vector&lt;T&gt;,即使TTriple&lt;int, int, int&gt;diffusionLimitedAggregateRandomWalk2D 返回std::vector&lt;std::pair&lt;int, int&gt;&gt;,也会编译。


建议的解决方案:声明一个模板函数并将其专门用于某些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);

【讨论】:

【参考方案2】:

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

【讨论】:

以上是关于问题将模板类型传递给函数并用于局部变量赋值 c++的主要内容,如果未能解决你的问题,请参考以下文章

以模板为函数参数的 C++ 自定义比较函数

将指向局部变量的指针传递给函数:它安全吗?

如何给全局变量赋值

js学习之函数的参数传递

typescript怎么定义全局的函数

java 强制类型转换的规则是啥?