Добавить функции-члены и переменные-члены на основе аргумента шаблона - PullRequest
0 голосов
/ 01 марта 2019

У меня есть семейство функций {f_n}, где f_0 непрерывно, f_1 непрерывно дифференцируемо, $ f_ {n} \ in C ^ {n} [a, b] $ и так далее.У меня есть класс C ++, который дает числовую оценку f_n через таблицу поиска для вектора v

template<int n, typename Real=double>
class f
{
public:
    f() { /* initialize v */ }

    Real operator()(Real x) { /* find appropriate index for x, and interpolate */}

private:
    std::vector<Real> v;
};

Однако, если f является дифференцируемой (n >= 1), я хочудобавить функцию-член:

template<int n, typename Real=double>
class f
{
public:
    f() { /* initialize v and dv */ }

    Real operator()(Real x) { /* find appropriate index for x, and interpolate on v */}

    Real prime(Real x) { /* find appropriate index for x, and interpolate on dv */}

private:
    std::vector<Real> v;
    std::vector<Real> dv;
};

Я также хотел бы добавить второй производный член для n> = 2, и так далее.Можно ли это сделать в одном классе?(Синтаксис C ++ 17 приемлем для меня.)

Ответы [ 2 ]

0 голосов
/ 07 марта 2019

Вы можете просто иметь функцию-член шаблона и static_assert, которая гарантирует, что вы не берете производную, которая не поддерживается вашим классом.Например:

template <int n, /* other stuff */>
class f
{
  /* Other stuff not shown */
  template <int p>
  Real prime(Real x)
  {
    static_assert(p <= n, "unsupported derivative");
    /* do whatever you need to to implement the pth derivative */
  }
};

Таким образом, объект типа f <1> будет поддерживать простое <1> (), но не простое <2> () и т. Д. Если вы случайно вызываете простое <3> для объектатипа f <1> компилятор вызовет вас на нем.Вам решать, хотите ли вы считать prime<0> идентичным operator () или изменить свой static_assert, чтобы включить проверку для p > 0.

0 голосов
/ 02 марта 2019

Для каждого n > 0 мы добавляем новую функцию-член, принимающую это значение в качестве аргумента, который наследуется от следующего уровня вниз:

template<int n, typename Real=double>
class f
    : public f<n-1, Real>
{
public:
    f() { /* initialize dv */ }

    using f<n-1, Real>::prime;
    Real prime(Real x, integral_constant<int, n>) { 
        /* find appropriate index for x, and interpolate on dv */
    }

protected:
    std::vector<Real> dv;
};

Где базовая версия добавляет operator():

template<typename Real=double>
class f<0, Real>
{
public:
    f() { /* initialize v */ }

    Real operator()(Real x) { /* find appropriate index for x, and interpolate */}
    Real prime(Real x) { return (*this)(x); }

protected:
    std::vector<Real> v;
};

Это означает, что первая производная вызывает prime(x, integral_constant<int, 1>{}), вторая производная вызывает prime(x, integral_constant<int, 2>{}) и т. Д.

...