繁体   English   中英

使用基于 CRTP 的类作为函数的参数,而不知道模板参数

[英]Using a CRTP based class as an argument of a function, without knowing the template parameter

我目前正在尝试编写一个微分方程求解器,并希望使用类作为运算符,它定义了一个重载的 operator() 以便我可以将运算符用作函子。 目标是我有一些数据,为了代表温度的参数,让我们取 T,我想提供一个接口,如 ddt(T) == laplacian(T),其中 ddt 是关于时间,拉普拉斯算子是关于空间的二阶偏导数。 在这个例子中,我只是在求解一个热方程。

因为我想允许不同的时间和空间方案,所以我想有两个时间和空间的基类,然后从这些基类派生出近似时间或空间的数值方案,其中我的 operator() 被定义为纯虚函数。

我希望能够从其 operator() 返回空间运算符的引用,因此我使用 CRTP 在基类中指定返回类型。

时间运算符位于等式的左侧,应该处理来自右侧的所有信息。 因此,在时间类中定义的 operator== 从右侧接收一个运算符。 问题就在这里: operator== 的参数要求我指定我传入的右侧运算符的类型,但是,我不知道我应该为模板参数使用哪种类型,因为我想稍后接受不同类型的运算符。 鉴于下面的代码,有没有一种干净的方法来解决这个问题?

#include <iostream>
#include <vector>

using Vector = std::vector<double>;

template<class Type>
struct spaceOperatorBase {
    virtual Type operator()(Vector &data) = 0;
    protected:
    Vector _data;
};

struct laplacianOperator : public spaceOperatorBase<laplacianOperator> {
    laplacianOperator operator()(Vector &data) final override {
        std::cout << "solving laplacian operator" << std::endl;
        this->_data = data;
        return *this;
    }
};

template <class Type>
struct timeOperatorBase {
    virtual Type operator()(Vector &phi) = 0;
    virtual void operator==(const spaceOperatorBase<laplacianOperator> &rhs) = 0; // <- how to get rid here of the dependency on <laplacianOperator>?
};

struct eulerOperator : timeOperatorBase<eulerOperator> {

    eulerOperator operator()(Vector &phi) {
        std::cout << "preparing time-integration" << std::endl;
        return *this;
    };

    void operator==(const spaceOperatorBase<laplacianOperator> &rhs) { // <- how to get rid here of the dependency on <laplacianOperator>?
        std::cout << "solving equation" << std::endl;
    };
};

int main() {

Vector T;
laplacianOperator laplacian;
eulerOperator ddt;

ddt(T) == laplacian(T);

return 0;
}

我终于想出了一个对我有用的方法。 当我使用 c++17 时,我可以使用 std::variant 和 std::visit 作为虚方法的参数类型。 这是满足我需要的完整代码。 把它贴在这里供任何在谷歌上搜索类似问题的人使用。

#include <iostream>
#include <vector>
#include <variant>

using Vector = std::vector<double>;

template<class Type>
struct spaceOperatorBase {
    virtual Type operator()(Vector &data) = 0;
    virtual void printMyType() const = 0;
    protected:
    Vector _data;
};

struct laplacianOperator : public spaceOperatorBase<laplacianOperator> {
    laplacianOperator operator()(Vector &data) final override {
        std::cout << "solving laplacian operator" << std::endl;
        this->_data = data;
        return *this;
    }
    void printMyType() const final override {
        std::cout << "I am a laplacian operator" << std::endl;
    }
};

// variant that holds all possible operators, can include multiple ...
using MyOperators = std::variant<laplacianOperator>;

template <class Type>
struct timeOperatorBase {
    virtual Type operator()(Vector &phi) = 0;
    virtual void operator==(const MyOperators &rhs) = 0; // <- how to get rid here of the dependency on <laplacianOperator>?
};

struct eulerOperator : timeOperatorBase<eulerOperator> {

    eulerOperator operator()(Vector &phi) {
        std::cout << "preparing time-integration" << std::endl;
        return *this;
    };

    void operator==(const MyOperators &rhs) { // <- how to get rid here of the dependency on <laplacianOperator>?
        std::cout << "solving equation" << std::endl;
        // accessing specific information from rhs
        auto operatorAccessor = [](const auto &accessor){
            accessor.printMyType();
        };
        std::visit(operatorAccessor, rhs);
    };
};

int main() {

Vector T;
laplacianOperator laplacian;
eulerOperator ddt;

ddt(T) == laplacian(T);

return 0;
}

这会将以下内容打印到控制台

preparing time-integration
solving laplacian operator
solving equation
I am a laplacian operator

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM