繁体   English   中英

C ++表达式模板模糊运算符重载

[英]C++ expression templates ambiguous operator overloading

我试图实现矢量和矩阵表达模板。有运算符+重载,但我得到模糊的运算符错误。

如何保留矩阵和向量的运算符,同时保留表达式模板的效果?

这是我的矩阵总和模板:

    template<typename E1, typename E2>
class MatSum: public MatExpression<MatSum<E1,E2>>{
    E1 const& _u;
    E2 const& _v;

public:
    MatSum(E1 const &u, E2 const &v): _u(u), _v(v){
        assert(u.height() == v.height() && u.width() == v.width());
    }

    double operator[](size_t i) const {return _u[i] + _v[i]; }

    size_t size() const {return _u.size();}
    size_t width() const {return _u.width();}
    size_t height() const {return _u.height();}
};

template<typename E1, typename E2>
MatSum<E1,E2> operator+(E1 const& u, E2 const& v){
    return MatSum<E1,E2>(u,v);
}

这里是矢量和模板:

template <typename E1, typename E2>
class VecSum : public VecExpression<VecSum<E1, E2>>{
    E1 const& _u;
    E2 const& _v;

public:
    VecSum(E1 const & u, E2 const &v): _u(u), _v(v){
        assert(u.size() == v.size());
    }

    double operator[](size_t i) const {return _u[i] + _v[i]; }
    size_t size() const {return _v.size(); }
};


template <typename E1, typename E2>
VecSum<E1, E2> operator+(E1 const &u, E2 const &v){
    return VecSum<E1,E2>(u,v);
}

以及导致错误的代码段:

    Vec v1 = {67.12,34.8,90.34};

    Vec v2 = {34.90,111.9,45.12};

    Vec sum = v1+v2;

Matrix m0 = {{1.0,1.0,1.0},{1.0,1.0,1.0},{1.0,1.0,1.0}};
    Matrix m1 = {{1.0,1.0,1.0},{1.0,1.0,1.0},{1.0,1.0,1.0}};

    Matrix summ = m0 + m0;

模板不能专门用于返回类型。

在您的情况下,编译器无法选择要调用哪个operator+因为它们都可以使用任何两种类型进行即时处理。 考虑这些例子:

Vec v1 = {67.12,34.8,90.34};
Matrix m1 = {{1.0,1.0,1.0},{1.0,1.0,1.0},{1.0,1.0,1.0}};
auto sum = v1+m1;

应该在这里调用哪两个运营商? 这对编译器来说很模糊。

您可以使用两个非模板运算符+,它们具有(Vec, Vec)(Matrix, Matrix)参数,或者使用SFINAE检查某些条件的模板运算符参数类型并替换所需的operator+

没有什么可以区分你的两个模板,所以这是一个模糊的调用。 您必须将返回MatSum那个限制为仅应用于类似矩阵的参数,和/或将返回VecSum仅应用于类似矢量的参数。

假设您using kind = Mat;添加成员别名using kind = Mat; MatExpressionMatrix ,并using kind = VecVecExpressionVector 然后我们做一个特质课

template<typename E1, typename E2, typename = typename E1::kind, typename = typename E2::kind>
struct Traits;

template<typename E1, typename E2>
struct Traits<E1, E2, Mat, Mat>
{
    using sum_type = MatSum<E1, E2>;
    // others, e.g. using prod_type = MatProd<E1, E2>;
};

template<typename E1, typename E2>
struct Traits<E1, E2, Vec, Vec>
{
    using sum_type = VecSum<E1, E2>;
    // others, e.g. using prod_type = VecProd<E1, E2>;
};

还有一些别名模板,例如

template<typename E1, typename E2>
using sum_t = typename Traits<E1, E2>::sum_type;

然后,我们可以将我们的+重载限制为仅在Traits存在时才存在。

template<typename E1, typename E2>
sum_t<E1, E2> operator+(E1 const& u, E2 const& v){
    return sum_t<E1, E2>(u, v);
}

暂无
暂无

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

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