有没有办法为函数指定通用参数,并限制它应该实现给定的接口

发布于 2024-08-20 18:10:08 字数 1102 浏览 4 评论 0原文

示例:

我有一个使用向量的函数:

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 元素作为前 2 个参数来调用它(与括号val() 相同),如果 std::vector 和 boost::array 是自变量实现后,我将能够从强制实施运算符[]的公共基类(类似接口)派生两者,因为两者都是库提供的,有什么方法可以强制转换/指定这样的限制吗?

我总是可以求助于普通的 c 数组,但它不是很简洁。

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

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;

}

Example:

I have a function that works with vectors:

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);
}

But now I want to call it with boost::array elements for the first 2 arguments (same with bracketval()), if std::vector and boost::array were self-implemented, I would be able to derive both from a common base class (interface-like) enforcing an implementation of operator[], since both are library-provided, is there any way to cast/specify such a restriction?

I can always resort to plain c-arrays, but it's not very neat.

Edit: FWIW, here is the original bracketval implementation:

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;

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

凉世弥音 2024-08-27 18:10:08

这适用于 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::array):

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

This works with std::vector, boost::array, built-in arrays an generally with anything that is indexable. I've also included a suggestion of how you should implement the bracketval function:

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);
    }    
}

You can even add an extra template parameter if you envision the possibility that the second vector could be of a different type that the first (e.g., the first a vector and the second a boost::array):

template <class VecX, class VecY, class VecOfVecs>
double interpolate2d(VecX const & xvals, VecY const & yvals, 
                     double xv, double yv,
                     VecOfVecs const & fvals)
无所谓啦 2024-08-27 18:10:08

虽然这对于您的特定问题来说可能有点过分,但通常您可以通过显式检查是否提供了某些成员以及某些表达式是否有效来检查模板参数是否实现特定接口。
Boosts 概念检查库为您提供了一种干净的方式这样做,但是容器检查类 它提供的内容对您没有帮助,因为 Boost.Array 仅支持序列要求的某个子集。

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

While this is probably overkill for your specific problem, in general you can check wether template parameters implement a certain interface by explicitly checking wether certain members are provided and some expressions are valid.
Boosts concept check library gives you a clean way to do that, but the container checking classes it provides don't help you here because Boost.Array only supports a certain subset of the sequence requirements.

What you could do though if you need a clean way to put restrictions is modelling the requirements yourself, either utilizing Boosts utilities or a similar custom approach.

来世叙缘 2024-08-27 18:10:08

无法对模板参数进行类型限制。您可以定义自己的接口并为您想要支持的所有类型创建适配器。

There is no way to put type restrictions on template parameters. What you could is, is define your own interface and create adaptors for all types you want to support.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文