Наследование для шаблонов классов - PullRequest
0 голосов
/ 18 ноября 2018

У меня есть три шаблона классов, использующих одни и те же данные членов и разные экземпляры одних и тех же методов.

Я хотел бы создать шаблон базового класса и позволить этим трем наследникам его наследовать:

#include <vector>
#include <memory>

template <typename Sde>
class EulerFdm
{
private:
std::shared_ptr<Sde> sde;
int NT;
public:
std::vector<double> x;  // The mesh array
double  k;              // Mesh size

double dtSqrt;
public:
EulerFdm() = default;
EulerFdm(const std::shared_ptr<Sde>& stochasticEquation, int numSubdivisions)
    : sde(stochasticEquation), NT(numSubdivisions)
{

    NT = numSubdivisions;
    k = sde->Expiry() / static_cast<double>(NT);
    dtSqrt = std::sqrt(k);
    x = std::vector<double>(NT + 1);

    // Create the mesh array
    x[0] = 0.0;
    for (std::size_t n = 1; n < x.size(); ++n)
    {
        x[n] = x[n - 1] + k;
    }
}

double  advance(double  xn, double  tn, double  dt, double  normalVar, double  normalVar2) const
{
    return xn + sde->Drift(xn, tn) * dt + sde->Diffusion(xn, tn) * dtSqrt * normalVar;
}
};


template <typename Sde>
class EulerHeun
{
private:
    std::shared_ptr<Sde> sde;
    int NT;
public:
    std::vector<double> x;  // The mesh array
    double  k;              // Mesh size

    double dtSqrt;
public:
    EulerHeun() = default;
    EulerHeun(const std::shared_ptr<Sde>& stochasticEquation, int numSubdivisions)
        : sde(stochasticEquation), NT(numSubdivisions)
    {
        NT = numSubdivisions;
        k = sde->Expiry() / static_cast<double>(NT);
        dtSqrt = std::sqrt(k);
        x = std::vector<double>(NT + 1);

        // Create the mesh array
        x[0] = 0.0;
        for (std::size_t n = 1; n < x.size(); ++n)
        {
            x[n] = x[n - 1] + k;
        }
    }

double  advance(double  xn, double  tn, double  dt, double  normalVar, double  normalVar2) const
{
    auto a = sde->Drift(xn, tn);
    auto b = sde->Diffusion(xn, tn);
    auto suppValue = xn + a * dt + b * std::sqrt(dt) * normalVar;

    return xn + 0.5 * (sde->Drift(suppValue, tn) + a) * dt
        + 0.5 * (sde->Diffusion(suppValue, tn) + b) * std::sqrt(dt) * normalVar;
}
};

template <typename Sde>
class FdmFRKI
{
private:
std::shared_ptr<Sde> sde;
int NT;
public:
std::vector<double> x;  // The mesh array
double  k;              // Mesh size

double dtSqrt;
public:
FdmFRKI() = default;
FdmFRKI(const std::shared_ptr<Sde>& stochasticEquation, int numSubdivisions)
    : sde(stochasticEquation), NT(numSubdivisions)
{
    NT = numSubdivisions;
    k = sde->Expiry() / static_cast<double>(NT);
    dtSqrt = std::sqrt(k);
    x = std::vector<double>(NT + 1);

    // Create the mesh array
    x[0] = 0.0;
    for (std::size_t n = 1; n < x.size(); ++n)
    {
        x[n] = x[n - 1] + k;
    }
}

double  advance(double  xn, double  tn, double  dt, double  normalVar, double  normalVar2) const
{
    auto sqrk = std::sqrt(dt);
    auto Wincr = sqrk * normalVar;

    auto F1 = sde->Drift(xn, tn);
    auto G1 = sde->Diffusion(xn, tn);
    auto G2 = sde->Diffusion(xn + 0.5 * G1 * (Wincr - sqrk), tn);

    return xn + (F1 * dt + G2 * Wincr + (G2 - G1) * sqrk);
}
};

Я попытался создать базовый класс FdmBase следующим образом:

template<typename Sde>
class FdmBase
{
protected:
       std::shared_ptr<Sde> sde;
       int NT;
public:
       std::vector<double> x;
       double k;
       double dtSqrt;
       FdmBase() = default;
       FdmBase(const std::shared_ptr<Sde>& stochasticEquation, int numSubdivision) : sde(stochasticEquation), NT(numSubdivisions)
{
    NT = numSubdivisions;
    k = sde->Expiry() / static_cast<double>(NT);
    dtSqrt = std::sqrt(k);
    x = std::vector<double>(NT + 1);

    // Create the mesh array
    x[0] = 0.0;
    for (std::size_t n = 1; n < x.size(); ++n)
    {
        x[n] = x[n - 1] + k;
    }
}
};

Однако программа не может скомпилироваться, когда я удаляю закрытые члены в производных классах.

Thisкак я называю это в методе main ():

auto fdm = std::shared_ptr<EulerFdm<Sde1>>(new EulerFdm<Sde1>(sde,NT));

1 Ответ

0 голосов
/ 18 ноября 2018

В наследовании вашего шаблона могут быть две разные проблемы, в зависимости от того, насколько точно вы адаптировали шаблоны для учета наследования.

Первая потенциальная проблема относится ко всем классам, включая не шаблонные классы: вы можете использовать только конструктор базового класса и прямые члены класса в mem-инициализаторах. Поэтому вам нужно переместить инициализацию sde и NT в тело конструктора с присваиванием или позволить конструктору базового класса инициализировать их. С не шаблонным базовым классом все было бы хорошо.

Но с шаблонными классами есть вторая проблема , связанная с тем, как выполняется разрешение имен . Это приводит к тому, что члены базового шаблонного класса не могут быть найдены в вашем примере, и приводят к сообщениям об ошибках, которые вы описываете. Это можно решить, сделав члены явно видимыми в производном классе, как в следующем примере:

template <typename T>
class B {
protected: 
    T a,b;  
public: 
    B() : a(10) 
    {
        b = a;  
    }
};
template <typename T> 
class C : public B<T> {
public: 
    using B<T>::b;   // Doesn't find these in the name resolution
    using B<T>::a;   // so just make them explicitly visible 
    C() //: a(20)
    {
        b = a +11; 
    }
};
int main() {
    C<double> x; 
    return 0;
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...