有没有办法为函数指定泛型参数,但是它应该实现给定的接口

时间:2010-02-10 13:34:13

标签: c++ arrays vector interpolation

示例:

我有一个适用于矢量的功能:

double interpolate2d(const vector<double> & xvals, const vector<double> & yvals, double xv, double yv, const vector<vector<double> > &fvals) {
    int xhi, xlo, yhi, ylo;
    double xphi, yphi;
    bracketval(xvals,xv,xhi,xlo,xphi);
    bracketval(yvals,yv,yhi,ylo,yphi);
    return (fvals[xhi][yhi]*xphi+fvals[xlo][yhi]*(1.-xphi))*yphi + (fvals[xhi][ylo]*xphi+fvals[xlo][ylo]*(1.-xphi))*(1.-yphi);
}

但是现在我想用前两个参数的boost :: array元素调用它(与bracketval()相同),如果std :: vector和boost :: array是自我实现的,我将能够派生出来两者都来自一个公共基类(类似于接口),强制执行operator [],因为两者都是库提供的,有没有办法转换/指定这样的限制?

我总是可以使用普通的c-arrays,但它不是很整洁。

编辑:FWIW,这是原始的benchval实现:

void bracketval(const vector<double> &vals, double v, int &hi, int &lo, double &prophi){
    hi=vals.size()-1;
    lo=0;
    while(abs(hi-lo)>1) {
        int md = (hi+lo)/2;
        if(vals[md]>v) hi=md; else lo=md;
    }
    if(vals[hi]!=vals[lo])
        prophi = (v-vals[lo])/(vals[hi]-vals[lo]);
    else
        prophi = 0.5;

}

3 个答案:

答案 0 :(得分:1)

这适用于std :: vector,boost :: array,内置数组,通常具有可索引的任何内容。我还提出了如何实现bracketval函数的建议:

template<class Vec>
void bracketval(Vec const & xvals, double xv, int xhi, int xlo, double xphi)
{
}

template <class Vec, class VecOfVecs>
double interpolate2d(Vec const & xvals, Vec const & yvals, 
                     double xv, double yv,
                     VecOfVecs const & fvals)
{
    int xhi, xlo, yhi, ylo;
    double xphi, yphi;
    bracketval(xvals,xv,xhi,xlo,xphi);
    bracketval(yvals,yv,yhi,ylo,yphi);
    return (fvals[xhi][yhi]*xphi+fvals[xlo][yhi]*(1.-xphi))
             *yphi + (fvals[xhi][ylo]*xphi+fvals[xlo][ylo]
             *(1.-xphi))*(1.-yphi);
}

int main()
{
    {
        std::vector<double> v, w;
        std::vector<std::vector<double> > vv;
        interpolate2d(v, w, 1., 2., vv);
    }
    {
        boost::array<double, 4> v, w;
        boost::array<boost::array<double, 4>, 4> vv;
        interpolate2d(v, w, 1., 2., vv);
    }
    {
        double v[4], w[4];
        double vv[4][4];
        interpolate2d(v, w, 1., 2., vv);
    }    
}

如果您想象第二个矢量可能与第一个矢量的类型不同(例如,第一个矢量和第二个boost ::数组),您甚至可以添加额外的模板参数:

template <class VecX, class VecY, class VecOfVecs>
double interpolate2d(VecX const & xvals, VecY const & yvals, 
                     double xv, double yv,
                     VecOfVecs const & fvals)

答案 1 :(得分:1)

虽然这对于您的具体问题可能有点过头了,但一般情况下,您可以通过明确检查是否提供某些成员并且某些表达式有效来检查其他模板参数是否实现某个界面。 Boosts concept check library为您提供了一种干净的方法,但它提供的container checking classes对您没有帮助,因为Boost.Array仅支持序列要求的某个子集

如果您需要一种简洁的方法来限制,您可以做的是自己对需求进行建模,使用Boosts实用程序或类似的自定义方法。

答案 2 :(得分:0)

无法对模板参数设置类型限制。你可以做的是定义你自己的界面并为你想要支持的所有类型创建适配器。