簡體   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