如何在类型擦除泛型类型上重载操作符?或者另一种方法呢?

时间:2017-09-18 10:14:57

标签: c++ templates operator-overloading type-erasure

前言:实际问题陈述

我原来的问题非常简单:如何为标量类型(算术类型)和其他类(如Matrix类,Vector类,Tensor类)创建一个通用容器,并使其行为正确,就好像我做标量+矩阵一样,MatrixVector,TensorMatrix,标量+标量等

我是如何解决它的

我正在尝试编写类型擦除类。我没有使用boost::type_erasure::any。这是我自己的练习,我相信使用该库对于这个小目的来说是不必要的。

代码

class var{
public:
    template <typename T>
    var(T val) : self_(std::make_unique<model<T> >(std::move(val))) {}
private:
    friend var operator+(const var& lhs, const var& rhs);

    class concept{
    public:
        virtual ~concept() = default;
        virtual std::unique_ptr<concept> copy_() const = 0;
    };

    template <typename T>
    class model final : concept {
        model(T x) : data_(std::move(x)) {}
        std::unique_ptr<concept> copy_() const override{
            return std::make_unique<model>(*this);
        }
        T data_;
    };
    std::unique_ptr<concept> self_;
};

var operator+(const var& lhs, const var& rhs){
    ... // do something here
}

想要什么

所以说我们有类似的东西:

var v1(3); // implicitly <int>
var v2(5.2); // implicitly <double> or <float>
v1 + v2; // implicitly <double> with value 8.2

同一班级可以照顾:

var v1(std::string("hello "));
var v2(std::string("world!"));
v1 + v2; // implicitly <std::string> with value "hello world!"

与此同时,我可以得到这些东西的载体:

vector<var> v;
v.emplace_back(std::string("hello ")); // no error
v.emplace_back(3); // no error either

我尝试了什么

我有想法提供加法器:

对于get_data(),

#1:模板概念
class var{
...
private:
    // Also make concept templated!
    template <typename T>
    class concept{
    public:
        virtual ~concept() = default;
        virtual std::unique_ptr<concept> copy_() const = 0;

        virtual T get_data(); 
    };

    template <typename T>
    class model final : concept<T> {
        model(T x) : data_(std::move(x)) {}
        std::unique_ptr<concept<T>> copy_() const override{
            return std::make_unique<model>(*this);
        }

        std::unique_ptr<concept<T>> adder(std::unique_ptr<concept<T>> rhs){
            return data_ + rhs->get_data();
        }
        T data_;
    };
    // this defeats the purpose of type erasure!
    std::unique_ptr<concept<T>> self_;
    ...
}

var operator+(const var& lhs, const var& rhs){
    return { lhs.self_->get_data() + rhs.self->get_data() };
}

#2:尝试对adder()

使用继承多态
class var{
...
    class concept{
    public:
        virtual ~concept() = default;
        virtual std::unique_ptr<concept> copy_() const = 0;
        // virtual ??? get_data(); What do I return here?
        //
        // template <typename T>
        // virtual T get_data(); // virtual cannot be defined on function templates!
    };

    template <typename T>
    class model final : concept {
        ...
        std::unique_ptr<concept> add(std::unique_ptr<concept> rhs){
            return data_ + rhs->get_data();
        }
        T data_;
    };
    std::unique_ptr<concept> self_;
};

var operator+(const var& lhs, const var& rhs){
    return { lhs.self_->adder(rhs.self_) };
}

如果类型擦除可能不是解决此类问题的正确方法,我该怎么办? (我想避免组合的重载次数)否则,是否有的解决方案当前的设置?

对于背景的解释,我试图用矩阵进行标量乘法(反之亦然),矩阵乘法用矩阵,标量乘法用标量。(这显然在这种情况下,它们都是数字的,但在此,为了清楚起见,我添加了一个std::string示例。

0 个答案:

没有答案