Есть ли способ указать универсальный аргумент для функции с ограничением, что она должна реализовывать данный интерфейс - PullRequest
2 голосов
/ 10 февраля 2010

Пример:

У меня есть функция, которая работает с векторами:

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 аргументов (то же самое с bravalval ()), если бы 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;

}

Ответы [ 3 ]

1 голос
/ 10 февраля 2010

Это работает с 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)
1 голос
/ 10 февраля 2010

Хотя это, вероятно, излишне для вашей конкретной проблемы, в общем случае вы можете проверить, что параметры шаблона шаблона реализуют определенный интерфейс, явно проверив, предоставляются ли определенные элементы и допустимы ли некоторые выражения.
Усиливает библиотека проверки концепции , дает вам простой способ сделать это, но классы проверки контейнера , которые она предоставляет, здесь вам не помогут, потому что Boost.Array поддерживает только определенное подмножество последовательность требования.

Что вы можете сделать, если вам нужен четкий способ наложения ограничений, так это моделировать требования самостоятельно, используя утилиты Boosts или аналогичный пользовательский подход.

0 голосов
/ 10 февраля 2010

Нет способа наложить ограничения типа на параметры шаблона. То, что вы могли бы, это определить свой собственный интерфейс и создать адаптеры для всех типов, которые вы хотите поддерживать.

...